1
cococaoliug 249 天前
因为 double 是整型,你得用 float 浮点数
|
2
rimwindy 249 天前 1
```
jshell> Double a = -0.57; System.out.println(a * 100); a ==> -0.57 -56.99999999999999 ``` 你指的是浮点数溢出吗?正如十进制无法精确表示 1/3 、1/6 、1/7 、1/9 一样,因为二进制中唯一的质因数是 2 ,所以只能精确表示 1/2 、1/4 、1/8 这样的数。 |
3
wenhuibrave 249 天前
java 中的 double 是一个 64 位的 IEEE 754 浮点数,这使得它在很多情况下足够精确,但对于某些数值,例如 0.57 ,就会出现这种舍入误差。
|
4
wenhuibrave 249 天前
想要输出-57 ,可以用 BigDecimal 表示,避免传统的浮点数舍入误差。
|
5
gitrebase 249 天前
|
6
Curtion 249 天前
|
7
sisi041 OP @wenhuibrave 如果不用 BigDecimal , 我 Math.round 一下,是不是也可以解决?
|
8
me1onsoda 249 天前
@cococaoliug double 是双精度浮点型。。
|
9
hapeman 249 天前 1
计算机实际存储是通过二进制进行的,所以存储非整型的数据时允许存在一定的误差
所以你输入的其实是一个近似于-0.57 的二进制数,你*100 之后就出现了丢失经度的情况 这一情况可以通过使用 BigDecimal 解决,需要注意的是在使用 BigDecimal 的构造函数初始化一个值的时候使用 String 类型而不是 Double ,使用 Double 也会丢失精度 在设计金额之类字段的时候一定不能使用 Double 、Float 等类型,请使用 BigDecimal |
10
andrewpsy 249 天前
对待楼主这种情况:
1. 如果有 BigDecimal 这类带精度的数值 type 那必须用。 2. 没有精度 type 的话尽量不用或少用除法。比如想把 2600 秒换算成分钟,尽量一直用秒甚至毫秒表示,这样不涉及除法。实在需要除法(想得到小时为单位的答案)就尽量整合除法只除一次。比如把 2600 秒/60/60=?小时变成 2600/(60*60),这时 round 只出现一次除法误差。 |
11
nitmali 249 天前
System.out.println(0.1 + 0.2);
|
12
githmb 249 天前
@cococaoliug 666
|
13
balalaFairty 249 天前
@sisi041 『如果不用 BigDecimal , 我 Math.round 一下,是不是也可以解决?』不能应对所有情况,不推荐这么做。如果你的应用场景里小数点只有 2 位,不涉及与其他浮点数的运算,并且下限不超过 [2^63-1, -2^63],你可以底层存储的时候改成 long 来存储和计算,最后展示输出的时候再除以 100 ,这样可以在大部分场景下避免使用 BigDecimal 。
|
14
sisi041 OP @balalaFairty 明白了,多谢
|
15
vituralfuture 248 天前 via Android
复习一下计算机组成原理就明白了,典型的浮点数误差,另外比较两个浮点数相等也一般不用==,而是判断两者差值是否足够小
|
16
hkdcl 246 天前 via Android
@cococaoliug 我支持你,op 太菜了
|
17
lixiaolin123 83 天前
Effective Java, Third Edition -Item 60: Avoid float and double if exact answers are required
|