This question already has answers here:
double or float datatype doesn't addup properly in a loop?
(5 answers)
Closed 6 years ago.
I am currently learnig java float-point numbers. I know, that a float have a specific amount of significant digets. I also know, that a float is represented in java like -1 or 1 * num * 10^x. Where num is the numer and 10^x is the decimal "point". But here we do not have a fraction of a number. How is a infinite loop here possible?
The code with infinite loop:
float f = 123456789;
while (f-- > 0) {
System.out.println(f);
}
It's about floating point arithmetic. When you're decrementing the number you stumble upon the situation when you go through the number f = 1.23456792E8 makes everything go wrong, because f-1 and f have the same floating point representation here. So decrementing makes the number be itself, which leads to the infinite loop. Just check:
System.out.println(1.23456792E8f);
System.out.println(1.23456792E8f - 1);
What is so special about the number and why execution stops there? It's because the floating point representation of 123456789 is 1.23456792E8. Already this gives us a gap of at least 3 due to the lack of precision of floating point numbers. Using double instead of float makes the program finish, but the issue will occur with higher numbers.
Related
This question already has answers here:
Integer division: How do you produce a double?
(11 answers)
Closed 6 years ago.
I'm currently working on a Trafficsimulation which is based on a grid system. For some reason the line of code, which calculates how many tiles i have to add always returns 0. I have tried it without the variables but it still doesn't work.
double blocksToAdd = o.getVelocity()*((1000/Main.FPS)/1000);
Currently the velocity is equal to 1.0f and the Simulation runs at 10 FPS, so blocksToAdd should be 0.1, but it always returns 0.
Since Main.FPS is an int, 1000/Main.FPS is also an int, equal to 100. You then proceed to calculate 100/1000. Since this is an integer division, only the "whole" part is taken, giving 0.
Using floating point literals will cause Java to use floating point division, which should produce the correct result:
double blocksToAdd = o.getVelocity() * ((1000.0 /Main.FPS ) / 1000.0);
// Here --------------------------------------^--------------------^
Most likely due to integer division tuncating the fraction.
Replace the first 1000 with 1000.0 and all will be well. (The latter is a floating point double literal which causes the division to be computed in floating point.) There are other remedies but I find this one to be the clearest.
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 8 years ago.
double test = 1029 / 9.8; // = 104.99999...
int inttest1 = (int) test; // 104
int inttest2 = (int)Math.floor(test); // 104
double testtt = 9.8 * 105; // 1029.0
1029 / 9.8 equals 105
but Java returns 104.9999...
More serious problem is integer casing result is 104, not 105
Why this happens and how can I avoid this result?
There are an infinite number of numbers, even in the limited range represented by Java. That's because mathematically, if you give me any two distinct numbers, I can average them to get a number between them. No matter how close they are.
And there are only a limited number of bits available to represent those numbers.
Hence, something has to give. What gives is the precision of the numbers. Not all numbers can be represented exactly, so some (the vast majority actually) are approximations.
For example, 0.1 cannot be represented exactly with IEEE754 encoding, even with a billion bits available to you.
See this answer for more information on the inherent imprecision of limited-storage floating point numbers.
Casting to an int implicitly drops any decimal. No need to call Math.floor() (assuming positive numbers)
To avoid this behavior use BigDecimal;
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
Standard floating point variables are in binary floating point. Many decimal floating point values (which are the ones you type in your code) have no exact representation in binary floating point. So it isn't doing the calculation with the exact numbers you entered but with some values very close to it. You can use Math.round to round the result to the precision you need and most likely the small error will disappear.
If you really need exact decimal calculation use BigDecimal but note that it is much slower.
This question already has answers here:
Int division: Why is the result of 1/3 == 0?
(19 answers)
Dividing by 100 returns 0
(6 answers)
Closed 9 years ago.
Would someone mind explaining why this doesn't work? All variables except for chance are ints, whereas chance is a double. When I print all the values they are definitely correct... but chance always comes out as 0.0. I know this has something to do with converting ints to doubles, as I have had an issue like this a couple of times before. What is the key to getting it to do what you want?
gladValue = (glad.dexterity+glad.tactical+weaponSkill);
oppValue = (glad.target.dexterity+glad.target.tactical+glad.target.agility);
chance = (gladValue/oppValue)*10.0;
Thanks
You should write gladValue * 10.0 / oppValue instead.
The reason is quite subtle. Your brackets mean that gladValue / oppValue is computed first. But these variables are integers so the result is an integer and therefore you lose the fraction part. Only when it is multipled by 10.0 will it get promoted to a double; but by then it's too late.
If you do as I say then, bearing mind that * and / have the same precedence and the operations happen from left to right, then when computing gladValue * 10.0, gladValue is promoted to floating point and that floating point result is divided by oppValue.
This question already has answers here:
java double precision [duplicate]
(2 answers)
Closed 9 years ago.
double d = 0.0;
for (int i = 0; i < 10; i++)
{
d = d+0.1;
}
System.out.println(d);
This is an example I read somewhere on "Principle of Least Surprise"
I was just curious on why the code would return a 0.999999999 and if I change the datatype of d to float, i get a 1.0000001. What is the reason behind such behavior.
This is a classic case of imprecision in floating point numbers. Since 0.1 can't be represented cleanly in binary (it is a repeating number), there is rounding error as the number is added to itself over and over. The difference in behavior when we change to a float just comes down to a difference in how 0.1 actually is held over the course of more bits of storage.
If you need really accurate representation of decimal numbers, the BigDecimal class will quickly become your best friend. Based on how it internally stores the details of your decimal without loss of precision, computations maintain their integrity.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Floating point arithmetic not producing exact results in Java
Floating point inaccuracy examples
In Java, given the following code:
double amount = scan.nextDouble();
tenBills = (int)amount / (int)10;
amount = amount - (tenBills * 10);
fiveBills = (int)amount / (int)5;
amount = amount - (fiveBills * 5);
After the first calculation, given an input of say 16 amount will equal 6.66 . But after the second calculation amount will be 1.6600000000000001 . I don't understand why subtracting an int from a double would cause such a result.
If you want a hardcore explanation, read the classic What Every Computer Scientist Should Know About Floating-Point Arithmetic. It explains why there are inevitably tiny rounding errors in floating point arithmetic like the one you're seeing.
If you just want a summary: Computers represent everything in binary. Binary representations while doing floating point arithmetic results in tiny inaccuracies in some situations.
Subtracting an int from a double does not change only the integer part of the double. It can also change the scale. In your particular case, the integer part before the subtraction (6) requires more bits to represent than the integer part after subtraction (1). This causes the entire representation of the number to allow for more fractional bits. Results can be (as you found out) a bit unexpected. (Pun intended)