The following does not compile:
int result = Math.random() + 1;
error: possible loss of precision
int result = Math.random() + 1;
^
required: int
found: double
but the following does compile:
int result = 0;
result += Math.random() + 1;
Why?
Putting the compilable code into a nested loop, one would expect result to increment by 1 with each iteration because Math.random() always returns a double whose value is less than 1 and when added to an integer the fractional part would be lost due to precision loss. Run the following code and see the unexpected result:
public class MathRandomCuriosity
{
public static void main(String[] args)
{
int result = 0;
for (int i = 0; i < 10; i++)
{
// System.out.println(result);
for (int j = 0; j < 20; j++)
{
// System.out.println(result);
for (int k = 0; k < 300; k++)
{
// System.out.println(result);
for (int m = 0; m < 7000; m++)
{
result += Math.random() + 1;
}
}
}
}
System.out.println(result);
}
}
With 10*20*300*7000 = 42,000,000 iterations the result should be 42,000,000. But it's not! The result varies i.e. 42,000,007 vs. 42,000,006 vs. 42,000,010 etc.
Why?
By the way...this is not code that is being used anywhere, it comes from a quiz I received in a newsletter. The reason for the nested loops is so that I can view the value of result at intervals.
Assigned operators like +=
do an implicit cast.
Note: in this case Math.random()
will be rounded down to 0 every time which is a significant loss of precision. ;)
However Math.random() + 1
has a very small chance of being rounded to 2. e.g. 1.999999 will be rounded to 1 but 1.9999999999999999 will be rounded to 2 (but the double +
operator rather than the cast to int
).
long l = Double.doubleToLongBits(1.0);
double d0_999etc = Double.longBitsToDouble(l -1);
System.out.println("The value before 1 is " +d0_999etc+" cast to (int) is "+ (int) d0_999etc);
System.out.println("The value before 1, plus 1 is " +(1+d0_999etc)+" cast to (int) is "+(int)(1 +d0_999etc));
prints
The value before 1 is 0.9999999999999999 cast to (int) is 0
The value before 1, plus 1 is 2.0 cast to (int) is 2
The details of an IEEE math implementation point out the loss of precision and unreliable results from double/float to integer conversion. For example I once found code that compared floating point numbers:
int x = 0;
if (a <= b)
{
x = y;
}
if (a > b)
{
x = z;
}
Sometimes the result was x == 0
eg a number the was caught by neither if statement, I had to rewrite the code as:
int x = 0;
if (a <= b)
{
x = y;
}
else
{
x = z;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With