Java 为什么我的for循环不能添加超过1.0/10000000.0的分数?

Java 为什么我的for循环不能添加超过1.0/10000000.0的分数?,java,for-loop,printing,add,fractions,Java,For Loop,Printing,Add,Fractions,我需要加一系列分数。我查看了其他有关添加分数的循环,但没有发现我遇到的问题。分数分母每次增加1.0,直到加起来1.0/1.0+1.0/2.0+1.0/ 150,000,000.0. 我的代码通过添加分数来工作,直到我在for循环中超过10000000。一旦我说15000000,它就不会打印任何东西,程序继续运行。我犯了什么错误?当答案高于某个数字时,为什么不打印 代码如下: float sum = 0; float numerator = 1; float denominator = 1; f

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

代码如下:

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);
浮点和=0;
浮动分子=1;
浮动分母=1;

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

在输出停止点,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。这也会使您的程序运行更长时间。如果您真的想超过此数量,请使用
BigDecimal
s。

而不是写更多注释。以下是我的想法:

浮点数的精度有限。这意味着,如果您添加非常非常小的数字,结果可能不是您预期的结果。另一种方法也有效-将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);




} 
}
公共类总和{
公共静态void main(字符串[]args){
//TODO自动生成的方法存根
浮点数和=0;
浮动分子=1;
int分母=1;//更改为int

for(int i=1;我尝试将精度更改为double(使用
double
而不是
float
)。将for循环中的
float
更改为
int
我必须使用float,因为它是用于类的。对于赋值,我必须“使用适当的数据类型来获得32位浮点”好吧,但是你应该被允许把<代码> i <代码>改为<代码> int >代码>。就像我说的,<代码>浮点< /代码>精度是有限的。也许这就是你的任务的重点。当你考虑一个现代CPU每秒可以执行的操作数时,邓10000000不是一个很大的数字。我的机器耗时35毫秒。要进行循环,你需要一个迭代数到几个数量级,甚至考虑“等待”因素。
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);




} 
}