For example, float a is 2.15, float b is 1.15, but a-b
will be 1.0000001
,
My first question is how to get the right answer 2.15-1.15=1
?
My second question is how to check the result of a minus b is an integer?
For example, float a is 2.15, float b is 1.15, but a-b
will be 1.0000001
,
My first question is how to get the right answer 2.15-1.15=1
?
My second question is how to check the result of a minus b is an integer?
For example, float a is 2.15, float b is 1.15.
Wrong. That's not possible.
A float
value is defined to be 32 bits large. That's a problem - basic mathematics: A 32-bit value can only contain 2^32 different possible values. That's about 4 billion. I know for a fact that there are far more than 4 billion numbers between 0 and 1 (in fact, there are an infinite amount of numbers). Let alone how many numbers exist between positive and negative infinity!
So how does this work? Is your computer a magic voodoo god that breaks the universe? No, of course not. Instead, only a bit less than 4 billion numbers are representable as a float
and all other numbers simply are not. Imagine the number line drawn out on a big board. Somebody tossed 4 billion darts at this thing, made a picture, and decreed: Only the darts are what you can store with a float
value. Anything in between 2 darts? Tough luck. Not representable.
2.15, 1.15? No dart. There is a dart really close to 2.15, and also one really really close to 1.15, though.
The rules of float
math are as follows: If the result of any mathematical operation is not a 'dart number', then it is silently rounded to the nearest dart.
The darts are not linearly distributed. There are many, many darts around 0 and 1. In fact, about as many darts are between 0 and 1 as there are darts above 1. As you get away from 0, there are fewer and fewer darts. Eventually (around 2^26 or so), the distance between 2 darts is more than 1, meaning, reallyLargeFloat + 1 == reallyLargeFloat
is true!! (because it is rounded to the nearest dart, which is the same dart).
The problem with 2.15-1.15 is: The actual thing that happens is:
You can't ask the system 'not to do the rounding silliness'. Because the universe and math and all that: 32-bits are what they are.
Thus, a few conclusions:
double
or float,
you really shouldn't do that, instead, do an 'epsilon compare': Is the difference between the 2 below some really tiny number? If yes, let's call them equal. So, don't do a - b == 1.0
, do: Math.abs(a - b) - 1.0 < 0.00001
. Yes, this is annoying.float
or double
. Instead, use ints/longs (e.g. if storing an amount in EU currency, do not store, say, 5.25
for something that costs 5 euros and 25 cents. Store 525
- the amount in cents. In a long
. Or, use BigDecimal
, but that is a very complicated tool that has a steep learning curve.% 1 == 0
. It should give you true.Something like:
public class MyClass {
public static void main(String args[]) {
double x = 2.15;
double y = 1.15;
double z = x - y;
System.out.println("Sum of x-y = " + z);
System.out.println("Sum of x-y = " + Math.round(z));
System.out.println("Sum of x-y = " + (z % 1 == 0));
}
}
The first question as covered in comments has an answer here Is floating point math broken?. To get the precise answer you can use BigDecimal, or work in Integer units of 100's or 1000's to suit your needs eg 215-115 = 100.
For your second question you can call Integer.parseInt(float)
, and as long as a NumberFormatException
is not thrown, then you know it was a valid Integer. You could do it a bit like this with a helper method:
float a = 2.15f;
float b = 1.15f;
float result = a-b;
System.out.println(isValidInteger(result));
//Helper method to check if the number is a valid integer
public static boolean isValidInteger(float number) {
try{
Integer.parseInt(number+"");
return true;
}
catch (NumberFormatException ex)
{
return false;
}
}
Hint: The result will always be false. If you want to get an integer from a float then use rounding with a tolerance as shown in the linked question.