[英]Floating Point Variable Not Working
When I run the program posted below, I get some weird results. 当我运行下面发布的程序时,我得到了一些奇怪的结果。
The program is suppose to print a message at multiples of when i = 5,000,000, however, it sometimes prints the message when i is not equal to a multiple of 5 million. 该程序假设以i = 5,000,000的倍数打印消息,但是,当i不等于500万的倍数时,它有时会打印消息。
When I change the numberOfTests from 50 million to 5 million, the program runs fine. 当我将numberOfTests从5000万更改为500万时,程序运行正常。 Also, if I change it from a float to a double, the program works fine as well.
此外,如果我将它从float更改为double,程序也可以正常工作。
What's wrong with my current code? 我目前的代码出了什么问题? Is the floating variable not working?
浮动变量不起作用吗? Why is this happening?
为什么会这样? How can I prevent this in the future?
我怎么能在将来防止这种情况发生?
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
This happens because of something called numeric promotion . 这是因为称为数字促销的事情。 Any time there is an expression involving two different types of numbers, the "narrowest" numbers are promoted to the "widest" numbers.
任何时候有一个表达涉及两种不同类型的数字,“最窄”的数字被提升为“最宽”的数字。
You have an expression like this here: 你有一个这样的表达式:
if(i % (IncrementsPercentageToPrintResults * numberOfTests) == 0)
Here, IncrementPercentageToPrintResults
is a float so it happens that every other number in the expression gets promoted to float. 这里,
IncrementPercentageToPrintResults
是一个浮点数,因此表达式中的每个其他数字都会被提升为浮点数。
The problem is that for large numbers, float is actually less precise than an int. 问题是,对于大数字,float实际上不如int精确。
So actually, for a float, after ±2^24 (±16,777,216), it cannot represent odd numbers anymore. 实际上,对于浮点数,在±2 ^ 24(±16,777,216)之后,它不能再代表奇数。 So a number like 19,999,999 gets rounded to 20,000,000.
所以像19,999,999这样的数字会变为20,000,000。 The larger the number is, the more imprecise floating point becomes.
数字越大,浮点变得越不精确。
There are a number of solutions and the best one here is to simply not multiply an int by a floating point fraction to do division. 有许多解决方案,这里最好的解决方案是不要将int乘以浮点分数来进行除法。 Just divide
numberOfTests
by 10: 只需将
numberOfTests
除以10:
if(i % (IncrementsPercentageToPrintResults / 10) == 0)
The other OK solution is to use double instead of float because double can represent all values in an int exactly. 另一个OK解决方案是使用double而不是float,因为double可以精确地表示int中的所有值。
Another is, if you really want, to cast the resulting float to an int: 另一个是,如果你真的想要,将生成的float转换为int:
(int)(IncrementsPercentageToPrintResults * numberOfTests)
However, the multiplication expression is still rounded to float so that only works here because float can represent the value 5,000,000 exactly. 但是,乘法表达式仍然舍入为浮点数,因此只能在此处起作用,因为float可以精确地表示值5,000,000。 Sometimes a cast like that is necessary but here it's not.
有时像这样的演员是必要的,但在这里不是。 Just use division or double.
只需使用除法或双倍。
The two obligatory links are: 这两个强制性链接是:
The problem is with the following line: 问题出在以下几行:
i % (IncrementsPercentageToPrintResults * numberOfTests)
(IncrementsPercentageToPrintResults * numberOfTests)
results in a float value because IncrementsPercentageToPrintResults
will typecast it to a float. (IncrementsPercentageToPrintResults * numberOfTests)
会产生浮点值,因为IncrementsPercentageToPrintResults
会将其类型转换为浮点数。 Float values shouldn't be used with the modulus operator because of how computers handle float values. 浮点值不应与模数运算符一起使用,因为计算机处理浮点值的方式。 A quick fix would be the following:
快速解决方案如下:
i % (int) (IncrementsPercentageToPrintResults * numberOfTests)
That'll cast the result to be an integer which fixes this issue. 这会将结果转换为修正此问题的整数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.