How does Java precisely display a double while it cannot be accurately expressed in binary scientific notation?

StackOverflow https://stackoverflow.com/questions/22526897

  •  17-06-2023
  •  | 
  •  

Pregunta

From my understanding, when assigning any double value to a variable, it will go through these steps :

  1. Convert to binary.
  2. Do some shifting in format of scientific notation.
  3. Convert to IEEE754.

Both step 1 and step 3 may introduce some inaccuracy. So the value stored in memory is already not accurate.

But surprisingly, if I don't do any calculation on this double and just print it out like: println(0.2d)

or even

println(1245.1325415d)

As long as the double is not too long, the result'd always be accurate.

Is there any tricks done when converting the IEEE754 format back to Base10 format?

¿Fue útil?

Solución

For each double D, there is a range of decimal fractions that would convert to D. Double.toString with D as argument yields the member of that range with the fewest significant digits. Often, a "not too long" decimal fraction is the member of its range with the fewest significant digits, so it is the one you get on conversion to String.

For example:

import java.math.BigDecimal;

public class Test {
  public static void main(String[] args) {
    double d1 = 0.4;
    double d2 = 0.400000000000000000001;
    System.out.println(d1);
    System.out.println(d2);
    System.out.println(new BigDecimal(d1));
  }
}

displays:

0.4
0.4
0.40000000000000002220446049250313080847263336181640625

Both "0.4" and "0.400000000000000000001" are in the range whose members convert to the double whose exact value is 0.40000000000000002220446049250313080847263336181640625. 0.4 is the shortest member of that range, so it is the result of the toString conversion. It is also a "not too long" decimal fraction.

Otros consejos

When you call print the double is internally converted to String .

So that what ever double value you pass will remain as accurate as you entered.

But this conversion is not Unlimited means if you enter 6789.78848376767676... this will not going to print exactly as there are some limitations.

For Example..

System.out.println(67670.65656565656566665);

gives output as 67670.65656565657 so there must be some limitations to represent double as String.

So If you want to check Manually try this...

String s=((Double)(67670.65656565656566665)).toString();
System.out.println(s);

this will result the same.

To know Behaviour of this thing TRY THIS

From the Double.toString() documentation:

How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double.

Bottom line: the formatter will output just enough digits to uniquely identitfy the value. So, for example, an actual value of 0.xxxxx...x4999 will be converted to the string 0.xxxxx...x5 when the predecessor and successor values are 0.xxxxx...x4837 and 0.xxxxx...x511 respectively. The illusion of precision is just that: an illusion based on happenstance.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top