Search code examples
javawhile-loopfloating-pointintegerprocessing

While loop not stopping at float 2.00


I'm a beginner trying to get this while loop so that the println table reads 2.00 15.000010, however it consistently stops on 1.9999993.

float weight = 60 ;
float height01 = 1.20 ;
float height02 = 2.00 ;

while( height01 < height02 ) {
    float BMI = ( weight / (height01 * height01) ) ;
    println( height01 + " , " + BMI ) ;
    height01 = height01 + 0.02 ;
}

The output reads:

1.9999993 , 15.0000105

I've tried using Math.round(height01) in order to convert the float to an int but this seems to do absolutely nothing.


Solution

  • Answer from a C point-of-view which applies to this Java post.

    A 32-bit float can exactly encode about 232 different values. 1.20 is not one of them. Finite float values are always a dyadic rational, some integer times a power of 2.
    With float height01 = 1.20 ;, height01 has a nearby value of 1.2000000476837158203125

    Adding 1.2000000476837158203125 often incurs a rounded sum. That sum is never 2.0.

    1.2000000476837158203125000
    1.2200000286102294921875000
    1.2400000095367431640625000
    ...
    1.9799993038177490234375000
    1.9999992847442626953125000
    2.0199992656707763671875000
    

    To fix,

    Use an integer loop count:

    float weight = 60.0f;
    float height01 = 1.20f;
    float height02 = 2.00f;
    float delta = 0.02f;
    long n = lround((height02 - height01)/delta);
    
    // iterate 0,1,2, ... n
    for (long i = 0; i <= n; i++) {
        float BMI = ( weight / (height01 * height01) ) ;
        println( height01 + " , " + BMI ) ;
        height01 = height01 + delta;
    }
    

    Or add tolerance to the limit detection of 1/2 the step

    float weight = 60.0f ;
    float height01 = 1.20f;
    float height02 = 2.00f;
    float delta = 0.02f;
    float height02plus = height02 + delta/2;
    
    while( height01 <= height02plus) {
        float BMI = ( weight / (height01 * height01) ) ;
        println( height01 + " , " + BMI ) ;
        height01 = height01 + delta;
    }
    

    Use f suffix for float constants. It makes a difference.


    Note: BMI is higher for taller individuals than shorter ones with the same body fat ratio..