story
0.3 is exactly representable in radix-10 floating point but not radix-2 FP (would be rounded to a maximum of 0.5 ulp error as seen in the title), for instance, just as 1/3 = 0.3333... is exactly representable in radix-3 floating point but neither radix-2 or radix-10 FP, etc.
> It's easy to write a program that sums up 0.01 until the result is not equal to n * 0.01.
It's not easy to do that if you use a floating point decimal type, like I recommended. For instance, using C#'s decimal, that will take you somewhere in the neighborhood of 10 to the 26 iterations. With a binary floating point number, it's less than 10.
Many languages have no decimal support built in or at least it is not the default type. With a binary type the rounding becomes already visible after 10959 additions of 1 cent.
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
bool compare(int cents, float sum) {
char buf[20], floatbuf[24];
int len;
bool result;
len = sprintf(buf, "%d", cents / 100 ) ;
sprintf(buf + len , ".%02d" , cents % 100 ) ;
sprintf(floatbuf, "%0.2f", sum) ;
result = ! strcmp(buf, floatbuf) ;
if (! result)
printf( "Cents: %d, exact: %s, calculated %s\n", cents, buf, floatbuf) ;
return result;
}
int main() {
float cent = 0.01f, sum = 0.0f;
for (int i=0 ; compare(i, sum) ; i++) {
sum += cent;
}
return 0;
}
Result: Cents: 10959, exact: 109.59, calculated 109.60
This is on my 64 bit Intel, Linux, gcc, glibc. But I guess most machines use IEEE floating point these days so it should not vary a lot.Precisely. That's why I specified ~ 10^26 addition operations.
But they still can't precisely represent quantities like 1/3 or pi.
Like commonly happens doing financial calculations, especially doing interest calculations.