Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
奇怪的Java分数行为_Java_Fractions - Fatal编程技术网

奇怪的Java分数行为

奇怪的Java分数行为,java,fractions,Java,Fractions,我在Java的double变量中看到了一个非常奇怪的行为,因为我试图简单地将小分数添加到double中,我看到了一个完全奇怪的结果 double test = 0; test += 0.71; test += 0.2; 现在我希望结果是: test = 0.91 对吧??错了 实际上,这是我在测试中得到的数字: test = 0.9099999999999999 现在,虽然这非常接近,但这是一个非常奇怪的分数损失,从长远来看,它会在我的程序中造成严重的错误 用一个浮点数,我甚至得到了一个更

我在Java的double变量中看到了一个非常奇怪的行为,因为我试图简单地将小分数添加到double中,我看到了一个完全奇怪的结果

double test = 0;
test += 0.71;
test += 0.2;
现在我希望结果是:

test = 0.91
对吧??错了

实际上,这是我在测试中得到的数字:

test = 0.9099999999999999
现在,虽然这非常接近,但这是一个非常奇怪的分数损失,从长远来看,它会在我的程序中造成严重的错误

用一个浮点数,我甚至得到了一个更奇怪的结果

任何帮助都将不胜感激


谢谢

这就是浮点值二进制编码的神奇之处查找IEEE754:。如果你想确保永远不会有这样的东西,你可能正在寻找BigDecimal:

基本规则:

处理浮点数时不要使用相等性测试必须测试间隙 通常使用十进制格式显示的整数 不要在金融应用程序中使用浮点数 只要您了解IEEE754,浮动通常是科学或工业操作的方式 double只能近似大多数分数值。这意味着您需要使用一些舍入,如果您想要得到预期的结果。或者,您可以使用BigDecimal来为您解决这个问题

double test = 0;
test += 0.71;
test += 0.2;
System.out.printf("%.2f%n", test);
印刷品

0.91
0.71 is actually 0.70999999999999996447286321199499070644378662109375
0.2 is actually 0.200000000000000011102230246251565404236316680908203125
0.71+0.2 is actually 0.9099999999999999200639422269887290894985198974609375
0.91 is actually 0.91000000000000003108624468950438313186168670654296875
0.71+0.2 == 0.91 is false
为了你自己的利益

System.out.println("0.71 is actually " + new BigDecimal(0.71));
System.out.println("0.2 is actually " + new BigDecimal(0.2));
System.out.println("0.71+0.2 is actually " + new BigDecimal(0.71 + 0.2));
System.out.println("0.91 is actually " + new BigDecimal(0.91));
System.out.println("0.71+0.2 == 0.91 is " + (0.71 + 0.2 == 0.91));
印刷品

0.91
0.71 is actually 0.70999999999999996447286321199499070644378662109375
0.2 is actually 0.200000000000000011102230246251565404236316680908203125
0.71+0.2 is actually 0.9099999999999999200639422269887290894985198974609375
0.91 is actually 0.91000000000000003108624468950438313186168670654296875
0.71+0.2 == 0.91 is false

这一点也不奇怪。0.91、0.71和0.2不能表示为IEEE754浮点值,因为当用二进制表示时,它们会有一个循环小数部分。这种情况完全类似于用有限的数字表示以10为底的1/3。你不能这么做


您看到的是一个舍入误差,这在进行浮点计算时是正常的。你必须对它进行编码。例如,你不能可靠地比较等式,你必须看到这两个数字之间的差值很小。要了解更深入但仍然可以理解的解释,请参阅。

Java使用所谓的浮点表示小数。它们使用指数表示法。我的意思是:

有一个乘数M和一个介于1023和-1022e之间的指数

数字N是这样表示的:M*2^E

4.25表示如下:

17*2^-2

0.91不能在base 2中精确表示,但Java可以非常接近:

0.909999999


因此,不可能准确地将这些数字加在一起。

这是一个很好的链接,可能是重复的-我建议在该网站上浏览一下。这里有很多要学的东西,而且非常简洁。那么你会如何解决我用一个大十进制数得到0.92的简单测试呢;内部二进制数表示为n、…、128、64、32、16、8、4、2、0、1/2、1/4、1/8、…、1/n。Ron,解决方案取决于具体的用例。大多数情况下,您不需要使用BigDecimal。如果您想检查数字是否相等,只需测试absa B打印数字还不够好,我指望得到正确的值,以便代码按预期工作。