具有长数据类型和浮点数据类型的Java算法
所以今天我注意到java中有一些意想不到的东西:具有长数据类型和浮点数据类型的Java算法,java,floating-point,algebraic-data-types,Java,Floating Point,Algebraic Data Types,所以今天我注意到java中有一些意想不到的东西: long a = 1234567890000l; float b = 1.2f; long result_a = (long)(a - b * 1000); long result_b = a - ((long) (b * 1000)); System.out.println("result_a: " + result_a); System.out.println("result_b: " + re
long a = 1234567890000l;
float b = 1.2f;
long result_a = (long)(a - b * 1000);
long result_b = a - ((long) (b * 1000));
System.out.println("result_a: " + result_a);
System.out.println("result_b: " + result_b);
你会期望结果_a和结果_b是相似的(不完全相同,因为b是浮动的,定义上不精确),对吗?正确的??嗯,不
result_a: 1234567954432
result_b: 1234567888800
不知道为什么会有这么大的差别。有什么想法吗?
float
和double
遇到了与二进制格式的有效位和系数的内部表示相关的问题
要解决此问题,您需要避免使用float
和double
进行精确(程序员选择的级别)计算。
您可以改用BigDecimal
从
不可变、任意精度有符号十进制数
只显示双值和浮点的值,考虑下面的代码:
if (1.0 - 0.6 - 0.3 - 0.1 == 0.0) {
// Will never enter here
}
测试结果为“假”,因为操作
1.0-0.6-0.3-0.1
不是零,而是由于舍入问题而接近零的值。好吧,你说这是一个巨大的差异。。。但差异在第8位有效数字。你期望的float
的精度有多高?为什么?(最接近123456789万的float是123456794432,首先……现在从这一点上减去1200,什么也没有发生,因为它太小了,相对而言,没有什么不同。)float
保证了7位有效的精度。Adouble
15。学会接受这个。请仔细研究@JonSkeet的第二条评论。@Bathsheba我会说,float
+1的精度为6位数,我不会真正使用“遭受”和“问题”这两个词,由于浮点数非常聪明,OP观察到的这种行为是设计出来的。事实上,它也不像BigDecimal
总是精确的,你不能在BigDecimal
中精确地表示1/3,就像你不能在double
中精确地表示1/10一样,但这是任意精确的。因此,这意味着开发人员选择的是精度级别。@Jon Skeet:我更新了响应以解释我对精度的定义。从根本上说,我认为尝试用几句话来解释这一点不太可能有多大帮助。如果您还不了解BigDecimal
和float
/double
之间的区别,我认为这个答案不会帮助您实现这一点。我把这个问题作为另一个问题的副本来结束,这个问题有更深入的答案。