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.
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..