Search code examples
javaintegerdouble

I do not understand why the value of the variable result is nonzero in this Java question


I have this question:

What do you think would be the value of the variable result after executing the following segment of Java code?

int i = 1234567890;

float f = i;

int result = i - (int)f;

The answer is nonzero

Bear in mind I am a beginner in java currently learning the absolute basics and frankly I do not understand why the answer is nonzero and what each line of the code actually means?


Solution

  • tl;dr

    If you want accuracy in your fractional numbers, use BigDecimal class rather than the float floating-point type.

    Floating-point is inaccurate

    The floating-point technology used by float/Float and double/Double trade away accuracy for speed of execution. Never use these types where accuracy is important, such as money.

    So converting an integer to a floating-point number and back again may not result in the same number.

    This behavior is not specific to Java. Java implements the electrical engineering standards defining floating-point arithmetic behavior. Any programming language supporting standard floating-point will show the very same issue.

    int i = 1234567890;                  // Create an integer number from literal input, and store as a primitive value in variable named `i`. 
    float f = i ;                        // Convert the integer `int` primitive to a fractional number represented using floating-point technology as a primitive value in variable named `f`. 
    int backAgain = (int)f ;             // Cast (convert) from a `float` type to a `int` type. Data-loss may be involved, as any fraction is truncated. 
    int result = i - backAgain ;         // Subtract one `int` primitive from the other `int` primitive. Store the integer result in a primitive `int` variable.
    boolean isZero = ( result == 0 ) ;   // Test if the result of our subtraction is zero. 
    

    See this code run live at IdeOne.com.

    i: 1234567890
    f: 1.23456794E9
    backAgain: 1234567936
    result: -46
    isZero: false
    

    BigDecimal

    If you want accuracy rather than speed when working with fractional numbers, use BigDecimal class.

    int i = 1234567890;
    BigDecimal bd = new BigDecimal( i ) ;
    int backAgain = bd.intValueExact() ;
    int result = i - backAgain ;
    boolean isZero = ( result == 0 ) ;
    

    See this code run live at IdeOne.com.

    isZero: true
    i: 1234567890
    bd: 1234567890
    backAgain: 1234567890
    result: 0
    isZero: true