This question already has answers here:
Why can't decimal numbers be represented exactly in binary?
(22 answers)
Floating point arithmetic not producing exact results [duplicate]
(7 answers)
Closed 9 years ago.
I'm simply trying to calculate percentage_imp, but instead of 0.22 (exactly 0.22, no rounding error), I get 0.22000000000000003!!
I used to get similar odd results, and I've been told to move from float to double, but this one is still odd!
All the variables below are double!
double percentage_imp= budget - (sum_minlessi)/ (sum_i + sum_lessi);
Thats because of the floating point precision values.
You must read:- What Every Computer Scientist Should Know About Floating-Point Arithmetic
You must also read how floating point arithmetic and its internal representation works.
0.22 is not representable as a double.
As an example, 1/3 cannot be represented in base-10, so we approximate with 0.3333333333333333.
Its a rounding error inherit in binary calculations. Not all rational decimal numbers can be represented as a single decimal number in binary. As such, when you perform operations such as multiply and divide, you'll get some nasty error on the last few digits.
Moving from double to float doesn't change this as double is simply a double precision floating point number.
I suggest you look at this link
As a extra bonus in java, simple operations such as binary multiplications are optimized as much as possible utilizing any sort of hardware optimizations when possible yielding different answers on different machines. If you require consistent behavior across all machines use the strictfp keyword in your class declaration.
Related
This question already has answers here:
Whats wrong with this simple 'double' calculation? [duplicate]
(5 answers)
Closed 9 years ago.
While I was having fun with codes from Java Puzzlers(I don't have the book) I came across this piece of code
public static void main(String args[]) {
System.out.println(2.00 - 1.10);
}
Output is
0.8999999999999999
When I tried changing the code to
2.00d - 1.10d still I get the same output as 0.8999999999999999
For,2.00d - 1.10f Output is 0.8999999761581421
For,2.00f - 1.10d Output is 0.8999999999999999
For,2.00f - 1.10f Output is 0.9
Why din't I get the output as 0.9 in the first place? I could not make any heads or tails out of this? Can somebody articulate this?
Because in Java double values are IEEE floating point numbers.
The work around could be to use Big Decimal class
Immutable, arbitrary-precision signed decimal numbers. A BigDecimal
consists of an arbitrary precision integer unscaled value and a 32-bit
integer scale. If zero or positive, the scale is the number of digits
to the right of the decimal point. If negative, the unscaled value of
the number is multiplied by ten to the power of the negation of the
scale. The value of the number represented by the BigDecimal is
therefore (unscaledValue × 10^-scale).
On a side note you may also want to check Wikipedia article on IEEE 754 how floating point numbers are stored on most systems.
The more operations you do on a floating point number, the more significant rounding errors can become.
In binary 0.1 is 0.00011001100110011001100110011001.....,
As such it cannot be represented exactly in binary. Depending where you round off (float or double) you get different answers.
So 0.1f =0.000110011001100110011001100
And 0.1d=0.0001100110011001100110011001100110011001100110011001
You note that the number repeats on a 1100 cycle. However the float and double precision split it at a different point in the cycle. As such on one the error rounds up and the other rounds down; leading to the difference.
But most importantly;
Never assume floating point numbers are exact
Other answers are correct, just to point to a valid reference, I quote oracle doc:
double: The double data type is a double-precision 64-bit IEEE 754
floating point. Its range of values is beyond the scope of this
discussion, but is specified in the Floating-Point Types, Formats, and
Values section of the Java Language Specification. For decimal values,
this data type is generally the default choice. As mentioned above,
this data type should never be used for precise values, such as
currency
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:
Is floating point math broken?
(31 answers)
Closed 8 years ago.
While running kmeans clustering in java the absolute difference between the data points 0.33 and 0.99 is displayed as 0.659999999 instead of 0.66.
Why is that?
Both the variables holding the data are of type double and I am using the Math.abs() function.
I saw such a problem only for 0.99. When subtracting using other values, the results were fine.
Thanks for any help
Floating-point datatype (float and double) can't be accurately represented in memory bits. They are approximately represented in memory.
Squeezing infinitely many real numbers into a finite number of bits
requires an approximate representation. Although there are infinitely
many integers, in most programs the result of integer computations can
be stored in 32 bits. In contrast, given any fixed number of bits,
most calculations with real numbers will produce quantities that
cannot be exactly represented using that many bits. Therefore the
result of a floating-point calculation must often be rounded in order
to fit back into its finite representation. This rounding error is the
characteristic feature of floating-point computation
What Every Computer Scientist Should Know About Floating-Point Arithmetic
This is how floating point numbers behave. They are not accurate.
Check this:- What Every Computer Scientist Should Know About Floating-Point Arithmetic
Also to add Floating point numbers use binary fractions and not decimal fractions. And if you need exact decimal values, you should use java.math.BigDecimal
You may check this answer as well for more reasoning and details:
Floating point rounding errors. 0.1 cannot be represented as
accurately in base-2 as in base-10 due to the missing prime factor of
5.
Doubles are not exact due to the way they are stored in memory. More information here:
https://en.wikipedia.org/wiki/Double-precision_floating-point_format
If you need an exact result, you should look into BigDecimal
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to round a number to n decimal places in Java
When multiplying two numbers in java happens this:
double a = 9.495 * 100;
Expected result:
a = 949.5;
But the obtained result is:
a = 949.4999999999999
When I try to round number 9.495 in two decimal places the result is 9.49 instead of 9.50
Any ideas how to solve this problem?
If you want accurate floating point computations, do not use the float or double types, but rather make use of the BigDecimal class.
This is a side effect of floating point calculations, and is well understood, but not necessarily intuitive. This question has actually been asked literally thousands of times, and you need to study how floating point arithmetic works.
To get around this, if you only need 2-decimal precision, then use a integer instead.
For example, if you're dealing with currency, and you want to buy a 100 items for $4.95, then you represent the cost of that value as the integer "495", an multiply that by 100, which gives you "49500". You always treat the last two digits as cents, so "49500" is $495.00.
You cannot. Floating point and double precision numbers in a computer cannot represent all possible values.
This question already has answers here:
Why does floating-point arithmetic not give exact results when adding decimal fractions?
(31 answers)
Closed 6 years ago.
I have 2 numbers stored as Double, 1.4300 and 1.4350. When I subtract 1.4350 - 1.4300, it gives me the result: 0.0050000000000001155. Why does it add 1155 to the end and how can I solve this so that it returns 0.005 or 0.0050? I'm not sure rounding will work as I'm working with 2 and 4 decimal numbers.
Oh, I love these... these are caused by inaccuracy in the double representation and floating-point arithmetic is full of these. It is often caused by recurring numbers in binary (i.e. base-2 floating-point representation). For example, in decimal 1/3 = 0.3333' In binary 1/10 is a recurring number, which means it cannot be perfectly represented. Try this: 1 - 0.1 - 0.1 - 0.1 - 0.1. You wont get 0.6 :-)
To solve this, use BigDecimal (preferred) or manipulating the double by first multiplying it something like 10000, then rounding it and then dividing it again (less clean).
Good question... it has caused huge problems in the past. Missiles overshooting targets, satellites crashing after launch, etc. Search the web for some, you'll be amazed!
This is a common pitfall with some computer representations of fractional numbers, see this question or google for floating point precision.
Double is not the right type for very precision floating point calculations, if you want exact results you have to use BigDecimal.