I want to understand how the Java double
type will store its value in memory in Java.
When I run the following code I get unexpected output:
public static void main(String[] args) {
float a = 1.5f;
float b= 0.5f;
double c= 1.5;
double d = 0.5;
float a1 = 1.4f;
float b1= 0.5f;
double c1= 1.4;
double d1 = 0.5;
System.out.println(" a- b is " + (a-b));
System.out.println(" c- d is " + (c-d));
System.out.println("a1-b1 is " + (a1-b1));
System.out.println("c1-d1 is " + (c1-d1));
}
Output:
a- b is 1.0 c- d is 1.0 a1-b1 is 0.9 c1-d1 is 0.8999999999999999
Why is c1-d1
not equal to 0.9
?
I also tried other different values but some time it return expected result and some time not.
A primitive type is predefined by the language and is named by a reserved keyword. Primitive values do not share state with other primitive values. The eight primitive data types supported by the Java programming language are: byte: The byte data type is an 8-bit signed two's complement integer.
The language defines eight Java primitive data types: boolean, float, double, byte, short, int, long and char. These eight Java primitive data types fall into the category of things that aren't objects. In a Java program, data always manifests itself as one of the eight primitive data types.
Data types are divided into two groups: Primitive data types - includes byte , short , int , long , float , double , boolean and char. Non-primitive data types - such as String , Arrays and Classes (you will learn more about these in a later chapter)
The string data type is a non-primitive data type but it is predefined in java, some people also call it a special ninth primitive data type. This solves the case where a char cannot store multiple characters, a string data type is used to store the sequence of characters.
While you might have heard about rounding errors, you might be wondering why you have a rounding error here.
float a1 = 1.4f;
float b1 = 0.5f;
double c1 = 1.4;
double d1 = 0.5;
System.out.println(new BigDecimal(a1) + " - " + new BigDecimal(b1) + " is " +
new BigDecimal(a1).subtract(new BigDecimal(b1)) + " or as a float is " + (a1 - b1));
System.out.println(new BigDecimal(c1) + " - " + new BigDecimal(d1) + " is " +
new BigDecimal(c1).subtract(new BigDecimal(d1)) + " or as a double is " + (c1 - d1));
prints
1.39999997615814208984375 - 0.5 is 0.89999997615814208984375 or as a float is 0.9
1.399999999999999911182158029987476766109466552734375 - 0.5 is
0.899999999999999911182158029987476766109466552734375
or as a double is 0.8999999999999999
As you can see, neither float
nor double
can represent these values exactly, and when the float or double is printed, some rounding occurs to hide this from you. In this case of float, the rounding to 7 decimal places yields the number you expected. In the case of double which has 16 digits of precision, the rounding error is visible.
As @Eric Postpischil, notes whether the float
or double
operation has a rounding error depends entirely on the values used. In this situation, it was the float which appeared to be more accurate even through the represented value was further from 0.9 than the double value.
In short: if you are going to use float
or double
you should use a sensible rounding strategy. If you can't do this, use BigDecimal.
System.out.printf("a1 - b1 is %.2f%n", (a1 - b1));
System.out.printf("c1 - d1 is %.2f%n", (c1 - d1));
prints
a1 - b1 is 0.90
c1 - d1 is 0.90
When you print a float or double, it assumes that the nearest short decimal value is the one you really want. i.e. within 0.5 ulp.
E.g.
double d = 1.4 - 0.5;
float f = d;
System.out.println("d = " + d + " f = " + f);
prints
d = 0.8999999999999999 f = 0.9
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