Reputation: 1418
I want to store values from 0.00 to 10.00 in doubles. I only need 2 digit precision. If I make no operations to the doubles, can I guarantee I will always get what I stored in the variables?
I was looking at this answer, and tested this code:
double a = 1.2;
double b = 1.1;
System.out.println(a - b);
System.out.println(a);
System.out.println(b);
The first print outputs an imprecise value, and the explanation, as I understood it, is how imprecisely the machine has to represent the numbers. But, why them the other two prints output precise values? Just because I made no operations? Can I assume it will always be true?
Upvotes: 0
Views: 281
Reputation: 223484
Java uses the IEEE-754 binary32 format for its double
type. This type has the property that, for numbers within its exponent range, if any decimal numeral of 15 or fewer significant digits is converted to double
(using round-to-nearest, ties-to-even), and the resulting double
is converted back to a 15-digit decimal numeral, the result equals the original number.
For default formatting of floating-point numbers, Java produces just enough digits to uniquely distinguish the number within the floating-point format.
A consequence of these two properties is that converting a decimal numeral with 15 or fewer significant digits to double
and then converting that back to decimal using the default formatting will produce something equal to the original number. It may differ in some respects. For example, the original numeral may have trailing zeros that the produced numeral does not, such as “3.00” to “3” or “123.4500” to “123.45”.
Upvotes: 0
Reputation: 96424
Here are some different attempts to print out the contents of a double value:
import java.math.*;
public class FloatShow {
public static void main(String ... args) {
System.out.println(1.2);
System.out.println(new Double(1.2).toString());
System.out.println(new BigDecimal(1.2).toString());
}
}
This prints out
1.2
1.2
1.1999999999999999555910790149937383830547332763671875
The println method given a double boxes it and calls toString, similarly the Double uses toString, which is doing some rounding for you. The BigDecimal uses the raw value to construct an instance, and presents it without cleanup. So your assumptions about precision were invalid.
Floating point and fixed decimal are two different concepts. Here is the definition of floating point arithmetic in wikipedia:
In computing, floating-point arithmetic (FP) is arithmetic using formulaic representation of real numbers as an approximation to support a trade-off between range and precision. For this reason, floating-point computation is often found in systems which include very small and very large real numbers, which require fast processing times.
But fixed decimal (like BigDecimal) is different, it stores the individual digits. BigDecimal is slower to use, but it doesn't make the kind of range-precision trade-off that floating point does.
Floating point is good for graphics and engineering applications where the calculation is the bottleneck, the inputs are not entirely precise (but precise within a known error range) and it can be calculated that the speed is worth the trade-off. For a lot of business applications the performance difference is not an issue because something else is always the bottleneck, values are known exactly, and accuracy is not negotiable.
Upvotes: 1
Reputation: 2342
The imprecision comes from representing the number as a double
(a floating point number).
Although it does use arithmetic on floating point values, as I said above, it is the storage of the values that is the problem, although printing methods often try to hide that from us. This answer should contain enough detail: https://stackoverflow.com/a/588014/1406083
If you want to store (and operate on) decimal numbers to a precision of two decimal points, and no more, then you should not be using double
s (or float
s). You should instead look to working with precise numbers (such as int
s or long
s). For two decimal points, you could just use 100 == 1.0
, or use the BigDecimal
class.
Upvotes: 1