2

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 ?

Jeffrey
  • 44,417
  • 8
  • 90
  • 141
Ajay
  • 2,976
  • 2
  • 28
  • 35

4 Answers4

4

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

Ruchira Gayan Ranaweera
  • 34,993
  • 17
  • 75
  • 115
Wenod Pathirana
  • 189
  • 1
  • 6
3

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
}
Dmitry Kuskov
  • 1,001
  • 6
  • 10
  • Although 23 bits are stored, for normalized numbers, including all conversions of int to float, there is an additional implicit bit. There are effectively 24 significant bits. Similarly double has 53 significant bits for normalized numbers. – Patricia Shanahan Jul 16 '13 at 04:46
  • Thanks Dmitry, Patricia – Ajay Jul 16 '13 at 05:26
3

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.

Jeffrey
  • 44,417
  • 8
  • 90
  • 141
1

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
Community
  • 1
  • 1
Ruchira Gayan Ranaweera
  • 34,993
  • 17
  • 75
  • 115