Floating-point pitfalls examples

Updated: 2024-08-23
Created: 2024-08

Gotchas

Generalities

Representation

Simple surprises

Equality

  • More surprises:
    $ perl -e 'printf ("%d\n",(0.1+0.2) == 0.3)'
    0
    $ perl -e 'printf ("%d\n",(1.0+2.0) == 3.0)'
    1
    $ perl -e 'printf ("%0.26f\n",(0.1+0.2) - 0.3)'
    0.00000000000000005551115123
    $ perl -e 'printf ("%d\n",((0.1+0.2)*10.0) == 3.0)'
    0
  • INF sort of works, NAN is weird (mode of knowledge):
    #include 
    
    int main()
    {
      float inf = 1.0f/0.0f;
      float nan = 0.0f/0.0f;
    
      printf("1.0f/0.0f: %0.26f\n",inf);
      printf("inf == inf: %d\n", inf == inf);
      printf("inf != inf: %d\n", inf < inf);
      printf("inf > inf: %d\n", inf > inf);
      printf("inf < inf: %d\n", inf < inf);
    
      printf("0.0f/0.0f: %0.26f\n",nan);
      printf("nan == nan: %d\n", nan == nan);
      printf("nan != nan: %d\n", nan < nan);
      printf("nan > nan: %d\n", nan > nan);
      printf("nan < nan: %d\n", nan < nan);
    
      return 0;
    }
    1.0f/0.0f: inf
    inf == inf: 1
    inf != inf: 0
    inf > inf: 0
    inf < inf: 0
    0.0f/0.0f: -nan
    nan == nan: 0
    nan != nan: 0
    nan > nan: 0
    nan < nan: 0
  • Using scaled tolerance:
    $ perl -e 'my ($a,$b,$c)=(0.1,0.00000003,0.09999997,0.1); printf ("%0.26f\n",($a-($b+$c)))'
    0.00000000000000001387778781
    $ perl -e 'my ($a,$b,$c)=(0.1,0.00000003,0.09999997,0.1); printf ("%d\n",($a-($b+$c)) < (0.000000000000001*($a+$b+$c)/2))'
    1
    $ perl -e 'my ($a,$b,$c)=(0.1,0.00000003,0.09999997,0.1); printf ("%d\n",($a-($b+$c)) < (0.0000000000000001*($a+$b+$c)/2))'
    0
  • Algorithm changes