在java中添加1/3会导致1.0,而不应该 [英] Adding 1/3 in java results in 1.0, while it shouldn't

查看:505
本文介绍了在java中添加1/3会导致1.0,而不应该的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:问题还是没有回答彻底!这个问题不涉及到浮点部分的截断问题!!!

在Java中我有这样简单的代码:

  double sum = 0.0; 
for(int i = 1; i <= n; i ++){
sum + = 1.0 / n
}
System.out.println(Sum should be: 1\" );
System.out.println(结果是:+ sum);

其中n可以是任何整数。对于像7,9这样的数字来说,sum的期望值是和sum的最后一位有差别,结果是0.999999999998或者什么,但是当我使用3时输出是 1.0



如果你增加1/3 3次,你会预期一个数字接近1,但我恰好是1.0。



为什么?

解决方案

我不确定这是否有助于澄清事情,因为我不确定是什么你认为是问题。



这是一个测试程序,使用BigDecimal,如前所述,显示中间答案的值。在最后一步中,将1.0 / 3的第三个副本添加到两个副本的总和中,确切的答案是在1.0和下一个比它低一半之间的一半。在这种情况下,round-to-even四舍五入规则选择1.0。

因此,我认为它应该是1.0到1.0,与这个问题相矛盾title。

测试程序:

$ p $ import java.math.BigDecimal ;

public class Test {
public static void main(String [] args){
final double oneThirdD = 1.0 / 3;
final BigDecimal oneThirdBD = new BigDecimal(oneThirdD);
final double twoThirdsD = oneThirdD + oneThirdD;
final BigDecimal twoThirdsBD = new BigDecimal(twoThirdsD);
final BigDecimal exact = twoThirdsBD.add(oneThirdBD);
final double nextLowerD = Math.nextAfter(1.0,0);
final BigDecimal nextLowerBD = new BigDecimal(nextLowerD);
System.out.println(1.0 / 3:+ oneThirdBD);
System.out.println(1.0 / 3 + 1.0 / 3:+ twoThirdsBD);
System.out.println(Exact sum:+ exact);
System.out.println(Rounding error rounding to 1.0:+ BigDecimal.ONE.subtract(exact));
System.out.println(最大的double小于1.0:+ nextLowerBD);
System.out.println(四舍五入错误舍入到下一个较低的double:+ exact.subtract(nextLowerBD));




$输出:

  1.0 / 3:0.333333333333333314829616256247390992939472198486328125 
1.0 / 3 + 1.0 / 3:0.66666666666666662965923251249478198587894439697265625
准确的总和:0.999999999999999944488848768742172978818416595458984375
舍入误差1.0:5.5511151231257827021181583404541015625E-17
最大的双倍小于1.0:0.99999999999999988897769753748434595763683319091796875
舍入误差向下舍入为下一个双精度值:5.5511151231257827021181583404541015625E-17


Note: question still not answered thoroughly! This questions does not deal with the issue of truncation of floating point parts!!!

In Java I have this simple code:

double sum = 0.0;
for(int i = 1; i <= n; i++){
    sum += 1.0/n
}
System.out.println("Sum should be: 1");
System.out.println("The result is: " + sum);

Where n can be any integer. For numbers like 7,9, the expected value for sum is to have difference in the last digits of sum, and the result is 0.999999999998 or something but the output when I use 3 is 1.0.

If you add 1/3 3 times, you would expect a number close to 1, but I get exactly 1.0.

Why?

解决方案

I'm not sure whether this will help clarify things, because I'm not sure what you consider to be the problem.

Here is a test program that uses BigDecimal, as previously suggested, to display the values of the intermediate answers. At the final step, adding the third copy of 1.0/3 to the sum of two copies, the exact answer is half way between 1.0 and the next double lower than it. In that situation the round-to-even rounding rule picks 1.0.

Given that, I think it should round to 1.0, contradicting the question title.

Test program:

import java.math.BigDecimal;

public class Test {
  public static void main(String[] args) {
    final double oneThirdD = 1.0/3;
    final BigDecimal oneThirdBD = new BigDecimal(oneThirdD);
    final double twoThirdsD = oneThirdD + oneThirdD;
    final BigDecimal twoThirdsBD = new BigDecimal(twoThirdsD);
    final BigDecimal exact = twoThirdsBD.add(oneThirdBD);
    final double nextLowerD = Math.nextAfter(1.0, 0);
    final BigDecimal nextLowerBD = new BigDecimal(nextLowerD);
    System.out.println("1.0/3: "+oneThirdBD);
    System.out.println("1.0/3+1.0/3: "+twoThirdsBD);
    System.out.println("Exact sum: "+exact);
    System.out.println("Rounding error rounding up to 1.0: "+BigDecimal.ONE.subtract(exact));
    System.out.println("Largest double that is less than 1.0: "+nextLowerBD);
    System.out.println("Rounding error rounding down to next lower double: "+exact.subtract(nextLowerBD));
  }
}

Output:

1.0/3: 0.333333333333333314829616256247390992939472198486328125
1.0/3+1.0/3: 0.66666666666666662965923251249478198587894439697265625
Exact sum: 0.999999999999999944488848768742172978818416595458984375
Rounding error rounding up to 1.0: 5.5511151231257827021181583404541015625E-17
Largest double that is less than 1.0: 0.99999999999999988897769753748434595763683319091796875
Rounding error rounding down to next lower double: 5.5511151231257827021181583404541015625E-17

这篇关于在java中添加1/3会导致1.0,而不应该的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆