Ajay
Ajay

Reputation: 3086

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 ?

Upvotes: 2

Views: 428

Answers (4)

Wenod Pathirana
Wenod Pathirana

Reputation: 190

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

Upvotes: 4

Ruchira Gayan Ranaweera
Ruchira Gayan Ranaweera

Reputation: 35557

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

Upvotes: 1

Dmitry Kuskov
Dmitry Kuskov

Reputation: 1021

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
}

Upvotes: 3

Jeffrey
Jeffrey

Reputation: 44808

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.

Upvotes: 3

Related Questions