Java 浮点变量不工作

Java 浮点变量不工作,java,Java,当我运行下面发布的程序时,我得到了一些奇怪的结果 假设程序在i=5000000时以倍数打印消息,但有时在i不等于500万倍数时打印消息 当我将numberOfTests从5000万更改为500万时,程序运行良好。另外,如果我将它从浮点改为双精度,程序也可以正常工作 我当前的代码有什么问题?浮动变量是否不工作?为什么会这样?我怎样才能防止将来发生这种情况 public static void main(String[] args) { final int numberOfTests = 5

当我运行下面发布的程序时,我得到了一些奇怪的结果

假设程序在i=5000000时以倍数打印消息,但有时在i不等于500万倍数时打印消息

当我将numberOfTests从5000万更改为500万时,程序运行良好。另外,如果我将它从浮点改为双精度,程序也可以正常工作

我当前的代码有什么问题?浮动变量是否不工作?为什么会这样?我怎样才能防止将来发生这种情况

public static void main(String[] args)
{
    final int numberOfTests = 50 * 1000 * 1000;
    final float IncrementsPercentageToPrintResults = .10f;

    for(int i = 1; i <= numberOfTests; i++)
    {
        if(i % (IncrementsPercentageToPrintResults * numberOfTests) == 0)
        {
            System.out.println("Currently at " + (int) (((float) i / numberOfTests) * 100) + "%." );
            System.out.println(" i = " + i);                
        }   
    }   

}

Output:
Currently at 10%.
 i = 5000000
Currently at 20%.
 i = 10000000
Currently at 30%.
 i = 15000000
Currently at 40%.
 i = 19999999
Currently at 40%.
 i = 20000000
Currently at 40%.
 i = 20000001
Currently at 50%.
 i = 24999999
Currently at 50%.
 i = 25000000
Currently at 50%.
 i = 25000001
Currently at 60%.
 i = 29999999
Currently at 60%.
 i = 30000000
Currently at 60%.
 i = 30000001
Currently at 70%.
 i = 34999998
Currently at 70%.
 i = 34999999
Currently at 70%.
 i = 35000000
Currently at 70%.
 i = 35000001
Currently at 70%.
 i = 35000002
Currently at 80%.
 i = 39999998
Currently at 80%.
 i = 39999999
Currently at 80%.
 i = 40000000
Currently at 80%.
 i = 40000001
Currently at 80%.
 i = 40000002
Currently at 90%.
 i = 44999998
Currently at 90%.
 i = 44999999
Currently at 90%.
 i = 45000000
Currently at 90%.
 i = 45000001
Currently at 90%.
 i = 45000002
Currently at 100%.
 i = 49999998
Currently at 100%.
 i = 49999999
Currently at 100%.
 i = 50000000
publicstaticvoidmain(字符串[]args)
{
最终整数测试=50*1000*1000;
最终浮点增量PercentagetOprintResults=.10f;

对于(int i=1;i而言,问题在于以下行:

i % (IncrementsPercentageToPrintResults * numberOfTests)
(IncrementsPercentageToPrintResults*numberOfTests)
生成浮点值,因为
IncrementsPercentageToPrintResults
将其类型转换为浮点。浮点值不应与模运算符一起使用,因为计算机处理浮点值的方式不同。快速修复方法如下:

i % (int) (IncrementsPercentageToPrintResults * numberOfTests)

这会将结果强制转换为整数,从而解决此问题。

发生这种情况是因为调用了某个函数。任何时候,当表达式涉及两种不同类型的数字时,“最窄”的数字都会升级为“最宽”的数

这里有这样一个表达式:

if(i % (IncrementsPercentageToPrintResults * numberOfTests) == 0)
这里,
IncrementPercentageToPrintResults
是一个浮点值,因此表达式中的每一个其他数字都会被提升为浮点值

问题是,对于大数,float实际上不如int精确

所以实际上,对于一个浮点,在±2^24(±16777216)之后,它不能再表示奇数了。所以像1999999这样的数字被四舍五入到20000000。数字越大,浮点就变得越不精确

有很多解决方案,这里最好的解决方案就是不要用整数乘以浮点分数进行除法。只需将
numberOfTests
除以10:

if(i % (IncrementsPercentageToPrintResults / 10) == 0)
另一个OK解决方案是使用double而不是float,因为double可以精确地表示int中的所有值

另一种方法是,如果您真的愿意,将生成的浮点值转换为int:

(int)(IncrementsPercentageToPrintResults * numberOfTests)
但是,乘法表达式仍然四舍五入为float,因此仅在此处有效,因为float可以精确表示5000000的值。有时需要这样的强制转换,但在此处不需要。只需使用除法或double

这两个强制性环节是:


我相信这会对这件事有所帮助。这很有帮助!谢谢可能的副本,答案如下1)它使用fp算术2)no 3)对整数值进行不正确的比较,这是由于fp类型固有的不精确性4)通过阅读和理解fp算术上的各种链接资源造成的。@StephenC我不认为这是该问题的重复,因为这里没有明显的浮点数学错误。问题在于
正在被提升和四舍五入。也许这一点以前已经得到了回答,但在那个主要关注分数算术的问题上并没有得到真正的回答。