0

The following code is terrible, but was encountered in a production situation. It was solved by doing something less insane - but I can't work out why the value remains constant. FWIW this arbitrary large value was taken from a timestamp.

#import <stdio.h>

int main(void)
{
    float wtf =  466056.468750;

    while(wtf > .01)
    {
        wtf -= .01;

        /* other operations here */

        printf("wtf = %f\n", wtf);
    }

    return 0;
}

When the program is run the output produced is

wtf = 466056.468750

wtf = 466056.468750

wtf = 466056.468750

wtf = 466056.468750

wtf = 466056.468750

wtf = 466056.468750

wtf = 466056.468750

wtf = 466056.468750

wtf = 466056.468750

wtf = 466056.468750

When debugging with, I can see that an appropriate value is returned for the expression wtf - .01 but it just doesn't seem to persist.

My question is, why isn't the decremented value stored in the variable?

In gdb the value of the operation is printed out as follows

10          printf("wtf = %f\n", wtf);
(gdb) p wtf
$1 = 466056.469
(gdb) p wtf - .01
$2 = 466056.45874999999
(gdb) n

Whilst there is a clear change in precision, the value 466056.45874999999 is neither 466056.469 nor 466056.468750 (the value printed to the console)

Community
  • 1
  • 1
rkachowski
  • 41
  • 5
  • 2
    does this maybe help: http://stackoverflow.com/questions/16124040/for-loop-with-float-as-counter-increasing-by-0-01-does-not-print-expected-floa ? – cruxi May 30 '14 at 10:06
  • Try your example starting with `float wtf = 42.;`. – alk May 30 '14 at 10:14

3 Answers3

5

466056.468750f and 466056.468750f - 0.01f both have the same representation as a float.

Floating point numbers have a finite representation. Multiple real numbers have the same floating point representation. Floating points are roughly logarithmically spaced and when the floating point number is bigger, there are more and more real numbers that have its same representation.

Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75
ouah
  • 142,963
  • 15
  • 272
  • 331
  • 1
    Technically, the number of real numbers between any pair of distinct real numbers is always uncountably infinite. It might be more accurate to say that size of the smallest change that can affect the value increases. – Patricia Shanahan May 30 '14 at 10:40
  • @PatriciaShanahan I agree. Technically when we talk about infinite we have to be careful as there is the same amount of real numbers between 0 and 1 as there is between between 0 and 10. I remember it was the results of the work by either Hilbert or Cantor. – ouah May 30 '14 at 11:34
  • As an alternative formulation, consider "more and more decimal fractions with only two digits after the decimal point". That is accurate, and relevant to the question. – Patricia Shanahan May 30 '14 at 15:43
4

Change the type of wtf from float to double. The float type has no precision for that number (read somewhere the web to understand the differences) Hope I could help!

Marco10
  • 87
  • 2
  • 8
  • Thanks, I understand the precision issue, i just don't know why the value isn't stored, and the result of the operation can be displayed correctly in gdb. – rkachowski May 30 '14 at 10:23
  • The value isn't stored because of the inprecision of the `float` type. – Marco10 May 30 '14 at 10:44
2

What's happening with your program is caused by floating point inaccuracy. The program will work as you expect if you replace float with double.

piokuc
  • 25,594
  • 11
  • 72
  • 102