double ddd = 16.24; // 默认情况下,Double 值的精度是 15 个十进制位,但内部维护最大精度是 17 位
ddd = ddd * 100;
断点看ddd是1623.99999...991
将double ddd = 16.25 或者 16.23 乘以100就是正常的 1625.00 和 1623.00 是什么原因?
------解决方案--------------------------------------------------------
浮点型做运算本身就不精确,大惊小怪啊。取自己需要的精度就好了
------解决方案--------------------------------------------------------
double、float类型本身就有精度误差
所以一般doble、float等类型比较不能直接用==,而是允许一定范围的误差
如:
double a=...;
if(Math.abs(a-0.5)<0.000001) //就认为a==0.5
------解决方案--------------------------------------------------------
double的计算本来就有误差.
你可以用decimal
decimal ddd = 16.24M;
ddd = ddd * 100;
------解决方案--------------------------------------------------------
这很简单,浮点数内部是二进制表示的,在转换成10进制的时候会有误差。
二进制数表示2的n次幂以及它的倒数时是最精确的。
比如 1 2 4 8 16 32 ...和 0.5 0.25 0.125 0.0625...
------解决方案--------------------------------------------------------
这就好比10进制数表示1 10 100 1000 以及 0.1 0.01 0.001 0.0001 ... 是最精确的。因为它们的前面、后面都是规整的0,在浮点数中,我们只要有阶码进行移位就可以了,而这些0本身却不用额外的空间存储。
------解决方案--------------------------------------------------------
如果要理解为什么ddd乘以100就等于1624,那么你要从二进制去理解,而不是从16.23999999999999....去理解。
------解决方案--------------------------------------------------------
浮点数都是不精确的,所以比较浮点数相等很麻烦,最好不要做相等的浮点数比较,设法化为不相等的比较,如果要比较相等,可以相减取绝对值然后小于某个很小的阈值来判断,很麻烦,
------解决方案--------------------------------------------------------
楼主需要温习下数据结构,就像在10进制中,小数点后面,第一位是0.1(10^-1),第二位是0.01(10^-2);
那么二进制中 ,小数点后第一位就是 0.5(2^-1),第二位就是 0.25 (2^-2).
同理,10 进制中每个小数小数点后表示为 d = n*0.1 + k*0.01 + m*0.001 + .......
二进制中,小数点后表示为 d = n*0.5 + k*0.25 + m*0.125 + ...;
那么对于小数数据,不管是double,float等,除了极个别的小数(比如16.25, 16.125)能精确表示(这意味着这些数能精确分解为上面的一个有限数列),其他都不能精确表示(就是只能分解为一个无穷的二进制数列)。这就是说小数是精确的。。
------解决方案--------------------------------------------------------
现在都不用double或float了,那个误差实在无法令人接收,直接使用统一类型decimal就好了,完全无计算误差,而且避免了带小数数值类型不一致而无法直接加减乘除运算的恶果。比如一个是double,另一个是float类型,显示的话,完全分不出,但是你让两者相加就会报错,提示无法将XXX转换为XXX。