BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / java / #47757同步于 2016/1/26
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖

double计算,看不明白,请教!

truthman
2016/1/26镜像同步11 回复
【jdk版本】 C:\Users\Administrator>java -version java version "1.6.0_30" Java(TM) SE Runtime Environment (build 1.6.0_30-b12) Java HotSpot(TM) Client VM (build 20.5-b03, mixed mode, sharing) 【代码】 public static void main(String[] args) { double a = 15070.3; double b = 7600.0; double c = a - b; System.out.println(a); System.out.println(b); System.out.println(c); } 【运行结果】 15070.3 7600.0 7470.299999999999 【问题】 计算结果为啥是 7470.299999999999 呢?
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
aiquestion机器人#1 · 2016/1/26
因为double的保存方式并不能精确保存0.3所以它保存了一个近似值。 所以一般判断double相等的代码都会用 abs(a-b)<10^-6的方式来。 【 在 truthman 的大作中提到: 】 : C:\Users\Administrator>java -version : java version "1.6.0_30" : Java(TM) SE Runtime Environment (build 1.6.0_30-b12) : ...................
icybee机器人#2 · 2016/1/26
参考楼上大神,逃
fuxuemingzhu机器人#3 · 2016/1/26
sf说的对
iamluo机器人#4 · 2016/1/26
又想起了设计电梯,浮点数用等号判断的那个梗 【 在 aiquestion 的大作中提到: 】 : 因为double的保存方式并不能精确保存0.3所以它保存了一个近似值。 : 所以一般判断double相等的代码都会用 abs(a-b)<10^-6的方式来。 : 【 在 truthman 的大作中提到 : .........
nuanyangyang机器人#5 · 2016/1/26
【 在 iamluo 的大作中提到: 】 : 又想起了设计电梯,浮点数用等号判断的那个梗 想起来还是觉得好玩,真人真事。 http://bbs.byr.cn/#!article/Picture/2812786
iamluo机器人#6 · 2016/1/26
哈哈,暴漫谁画的?太有才了! 【 在 nuanyangyang 的大作中提到: 】 : : 【 在 iamluo 的大作中提到: 】 : : 又想起了设计电梯,浮点数用等号判断的那个梗 : : 想起来还是觉得好玩,真人真事。 http://bbs.byr.cn/#!article/P : .........
nuanyangyang机器人#7 · 2016/1/26
认真地回答一下吧:IEEE754的double型数的格式如下: S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 64位二进制,第一位是符号位,0为正,1为负;之后11位是指数部分,之后52位是小数部分。 这个数表示S 1.FFFFFFFFF……FFF * 2^(EEEEEEEEEEE - 1023),即:底数是那一堆F前面加上“1.”;指数是那些E组成的二进制整数减去1023。 比如,24.0可以精确地表示为:0 10000000011 1000000000000000000000000000000000000000000000000000 其中,指数部分10000000011用十进制表示是1027;底数是1.1000000000000000000000000000000000000000000000000000,用十进制表示就是1.5。 所以这个数就是1.5 * 2^(1027 - 1023) = 1.5 ^ 2^4 = 1.5 * 16 = 24 但15070.3不能精确地用二进制小数表示,因为那个.3用十进制可以有限地表示,但用二进制是除不尽的,是二进制的循环小数。 所以,用IEEE754 double只能近似表示。最接近15070.3的能表示的数就是: 0 10000001100 1101011011110010011001100110011001100110011001100110 看到后面的循环小数1100 1100 1100……了吧 幸运的是,7600.0可以精确地表示: 0 10000001011 1101101100000000000000000000000000000000000000000000 试试做它们的减法。它们的指数只相差1。我们就把指数统一起来,这两个数的差就是: ( 1.1101011011110010011001100110011001100110011001100110 -0.11101101100000000000000000000000000000000000000000000) * 2^(1036-1023) = 0.1110100101110010011001100110011001100110011001100110 * 2^13 = 1110100101110.010011001100110011001100110011001100110 约等于十进制的7470.299999999 用IEEE754 double表示这个数,就是 0 10000001011 1101001011100100110011001100110011001100110011001100 但和7470.3最接近的是 0 10000001011 1101001011100100110011001100110011001100110011001101 应该就是最后那个0和1的差别造成了打印出7470.2999999999吧。
truthman机器人#8 · 2016/1/26
拜读了!多谢。 【 在 nuanyangyang 的大作中提到: 】 : 认真地回答一下吧:IEEE754的double型数的格式如下: : S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF : 64位二进制,第一位是符号位,0为正,1为负;之后11位是指数部分,之后52位是小数部分。 : ...................
truthman机器人#9 · 2016/1/26
想再请教个问题。这个实际是项目中遇到的问题,涉及到的实际是钱数的比较。那这咋比较啊?我就是用15070.3和另外两笔钱7600.0和7470.3两笔钱进行的比较。 【代码】 import java.util.ArrayList; import java.util.List; public class Test11 { public static void main(String[] args) { dealWithDetailList(15070.3); } private static void dealWithDetailList(double canVerifiAmount4Detail){ if(canVerifiAmount4Detail == 0) return; List<Account> detailList = new ArrayList<Account>(); detailList.add(new Account(0.0,7600.0,2)); detailList.add(new Account(0.0,7470.3,2)); List<Account> needDealList = new ArrayList<Account>(); if(detailList.size()>0){ for(Account po:detailList){ double unVerificationAmount = po.getUnVerificationAmount(); double verificationAmount = po.getVerificationAmount(); if(unVerificationAmount == 0) continue; if(unVerificationAmount <= canVerifiAmount4Detail){ verificationAmount = verificationAmount + unVerificationAmount; po.setVerificationAmount(verificationAmount); po.setStatusId(6); canVerifiAmount4Detail = canVerifiAmount4Detail - unVerificationAmount; needDealList.add(po); if(canVerifiAmount4Detail == 0) break; } else{ verificationAmount = canVerifiAmount4Detail + verificationAmount; po.setVerificationAmount(verificationAmount); unVerificationAmount = unVerificationAmount - canVerifiAmount4Detail; po.setStatusId(5); needDealList.add(po); break; } } for(Account po:needDealList){ System.out.println("VerificationAmount-" + po.getVerificationAmount() + "-UnVerificationAmount-" + po.getUnVerificationAmount() + "-StatusId-" + po.getStatusId()); System.out.println("========================"); } } } } class Account{ private Double verificationAmount; private Double unVerificationAmount; private Integer statusId; public Account(Double verificationAmount,Double unVerificationAmount,Integer statusId){ this.verificationAmount = verificationAmount; this.unVerificationAmount = unVerificationAmount; this.statusId = statusId; } public Double getVerificationAmount() { return verificationAmount; } public void setVerificationAmount(Double verificationAmount) { this.verificationAmount = verificationAmount; } public Double getUnVerificationAmount() { return unVerificationAmount; } public void setUnVerificationAmount(Double unVerificationAmount) { this.unVerificationAmount = unVerificationAmount; } public Integer getStatusId() { return statusId; } public void setStatusId(Integer statusId) { this.statusId = statusId; } } 【 在 nuanyangyang 的大作中提到: 】 : 认真地回答一下吧:IEEE754的double型数的格式如下: : S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF : 64位二进制,第一位是符号位,0为正,1为负;之后11位是指数部分,之后52位是小数部分。 : ...................