【问题标题】:Why wont my for loop add fractions past 1.0/10,000,000.0?为什么我的 for 循环不会添加超过 1.0/10,000,000.0 的分数?
【发布时间】:2016-05-02 12:22:09
【问题描述】:

我需要添加一系列分数。我在添加分数时查看了其他 for 循环,但没有遇到我遇到的问题。分数分母每次增加 1.0,直到加起来 1.0/1.0 + 1.0/2.0 + .... + 1.0/ 150,000,000.0。我的代码通过添加分数来为我工作,直到我在我的 for 循环中超过 10,000,000。一旦我说 15,000,000,它就不会打印任何东西,程序会继续运行。我犯了什么错误?为什么超过一定数量时不打印答案?

代码如下:

float sum = 0;
float numerator = 1;
float denominator = 1;

for(float i = 1; i <= 10000000; i++)
{
    sum = ((float)numerator/denominator) + sum;
    denominator++;
}
System.out.println("The sum is " + sum);

【问题讨论】:

  • 尝试将精度更改为双精度(使用double 而不是float)。并将for循环中的float更改为int
  • 我必须像上课一样使用浮点数。对于作业,我必须“使用适当的数据类型来获得 32 位浮点”。
  • 好的,但是应该允许您将i 更改为int
  • 就像我说的,float 精度是有限的。也许这就是你的任务的重点?
  • @Dunno 10000000 当您考虑现代 CPU 每秒可以执行的操作数时,这根本不是一个大数字。我的机器花了 35 毫秒来执行循环。您甚至需要大几个数量级的迭代计数才能考虑“等待”因素。仅供参考:)

标签: java for-loop printing add fractions


【解决方案1】:

1 添加到足够大的float 将不再有任何效果。问题是float 的精度有限——23 位。一旦达到约 1600 万(约 224),连续浮点值之间的差值大于 1。您可以通过打印出 Math.ulp 的结果来看到这一点(最后一个单位)价值。

if (denominator % 1000 == 0)
    System.out.println("Denominator is " + denominator + ", ulp is " + Math.ulp(denominator));

在输出停止点,ulp 为 1.0。

...
Denominator is 1.6775E7, ulp is 1.0
Denominator is 1.6776E7, ulp is 1.0
Denominator is 1.6777E7, ulp is 1.0

在224,ulp跳到2.0,加上1.0遵循IEEE的轮向偶数规则,总和不变。

将数据类型更改为double 以获得更大的精度(53 位)。请注意,此更改只会延长问题,直到您达到 253。这也会使您的程序运行时间更多。如果你真的想超过这个数量,请使用BigDecimals。

【讨论】:

    【解决方案2】:

    我的想法不是在这里写更多的cmets:

    浮点数的精度有限。这意味着如果你添加非常非常小的数字,结果可能不是你所期望的。它也适用于其他方式 - 将 1 添加到非常大的数字不会改变它的值。

    在您的程序中,为了避免这个问题,您应该增加整数值并在求和之前将它们转换为浮点数。像这样:

    public class Sum {
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
    
    
        float sum = 0;
        float numerator = 1;
        int denominator = 1; //changed to int
    
        for(int i = 1; i <= 10000000; i++)
        {
            sum = (numerator/(float)denominator) + sum; //this casts denominator to float
            denominator++; //this will now increment integer
    
        }
        System.out.println("The sum is " + sum);
    
    
    
    
    } 
    }
    

    延伸阅读:Floating point on wikipedia

    【讨论】:

      猜你喜欢
      • 2018-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多