简体   繁体   中英

int and double divided by double java

How do I explain the below:

    double o = 2.3;
    int i = (int) (o * 100000.0);
    double d = i / 100000.0;
    System.out.println(d);

prints 2.29999

    double o = 2.3;
    double i = o * 100000.0;
    double d = i / 100000.0;
    System.out.println(d);

prints 2.3

When dividing an int by double doesn't java first cast the int as a double then do the division - if so the two code blocks should effectively print the same value?

There seems to be some IEEE 754 floating point precision specifications I'm missing and/or jvm optimizations that inlines

 double i = 2.3 * 100000.0;
 double d = i / 100000.0;

as double d = 2.3 * 100000.0 / 100000.0; effectively cancelling out the division and making this a no-op.

Thoughts?

2.3 is not exactly representable in IEEE-754 64-bit binary floating-point. What happens in your first code sequence is:

  • The source text 2.3 is converted to the nearest representable value, 2.29999999999999982236431605997495353221893310546875.
  • The exact mathematical result of multiplying that by 100000 is not exactly representable either, so it is rounded to 229999.99999999997089616954326629638671875.
  • When this is converted to an int , the conversion truncates, producing 229999.
  • Dividing that by 100000 rounds again, producing 2.29999000000000020094148567295633256435394287109375.
  • When the above is printed, Java displays it as “2.29999”.

There seems to be some IEEE 754 floating point precision specifications I'm missing

When you use (int) it truncates the fractional part no matter how close it is to the next whole value. It is not reversible as information is lost, so it should be no surprise that you don't get the same result.

What you could do instead is the following

double o = 2.3;
long l = Math.round(o * 100000.0);
double d = l / 100000.0;
System.out.println(d);

jvm optimizations that inlines ... making this a no-op

The JVM might optimise it, but it won't change the result. If an optimisation changes the outcome it is a bug in the optimiser.

double i = o * 100000.0;

The value of i after this is 229999.99999999997 (you can see this yourself by adding a simple print statement; it's due to floating-point inaccuracies ).

int i = (int) (o * 100000.0);

The value of i after this is 229999 (ie the value above with the fractional part truncated due to the int cast).

Therefore, in the line

double d = i / 100000.0;

you are using two numerically different i values in your two snippets (ie they differ by about 1), hence the different outputs.

You are correct in saying that when dividing an int by a double, the int is first converted to a double (this is done through the bytecode instruction i2d ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM