具有长数据类型和浮点数据类型的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

所以今天我注意到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: " + 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位有效的精度。A
double
15。学会接受这个。请仔细研究@JonSkeet的第二条评论。@Bathsheba我会说,
float
+1的精度为6位数,我不会真正使用“遭受”和“问题”这两个词,由于浮点数非常聪明,OP观察到的这种行为是设计出来的。事实上,它也不像
BigDecimal
总是精确的,你不能在
BigDecimal
中精确地表示1/3,就像你不能在
double
中精确地表示1/10一样,但这是任意精确的。因此,这意味着开发人员选择的是精度级别。@Jon Skeet:我更新了响应以解释我对精度的定义。从根本上说,我认为尝试用几句话来解释这一点不太可能有多大帮助。如果您还不了解
BigDecimal
float
/
double
之间的区别,我认为这个答案不会帮助您实现这一点。我把这个问题作为另一个问题的副本来结束,这个问题有更深入的答案。