简体   繁体   中英

loss of precision during widening conversions

Output of the below code is

package com.ajay.compoitepattern;
class Test {
        public static void main(String[] args) {
                int big = 1234567890;
                float approx = big;
                System.out.println(big - (approx));
                System.out.println(big - (int)(approx));
        }
}

The outptut to this program is

0.0
-46

My question is , if the precision was lost in the widening conversion it should have been -46 in the first sysout also, why is the first output 0.0 ?

First output is 0.0 because float substract from an int and it makes whole statement in to float.

That means int big also converted into a float value. Basically you are doing is (approx - approx) as (float)big = approx. This should be the reason why you are getting zero.

If you want just try this one too

System.out.println(big/(approx));

Operations between int and float converts the whole statement into float

float in Java uses 23 bit for mantissa, plus 1 implisit bit, hence 24 significant bits are available, and int is represented by 32 bits. So there is inevitable loss of precision for int values higher than 2^23. You should use double here, as it has a 53 significant bits, so the result will be 0 in second case.

public static void main(String[] args) {
    int big = 1234567890;
    double approx = big;
    System.out.println(big - (approx)); // --> 0.0
    System.out.println(big - (int) (approx)); // --> 0
}

This is covered by JLS §4.2.4 :

If at least one of the operands to a binary operator is of floating-point type, then the operation is a floating-point operation, even if the other is integral.

In your first example, big - approx , since approx is a float , this counts as a floating-point operation. big is widened into a float , and since approx is also big widening into a float , the loss of precision cancels itself out, netting you an answer of zero.

In your second example, big - (int) approx , neither operand is a floating-point type since you casted approx to int . The loss of precision is now present, and your answer is no longer zero.

Read this may help you to understand. Read this SO post too..

Let's consider your code

    int big = 1234567890;     // here your int big=1234567890;
    float approx = big;
    BigDecimal bd=BigDecimal.valueOf(approx);
    System.out.println(bd);  // Now you can see int to float creates approx= 1234567936;
    System.out.println(big - (approx));     // In here big again casting to float since you are doing a operation with float, result is zero.
    System.out.println(big - (int)(approx)); // here big=1234567890 and approx= 1234567936. so difference is -46

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