Perl for looping

I have a simple for loop in Perl

for ($i=0; $i <= 360; $i += 0.01)
{
print "$i ";
}

Why, when I run this code, I get the following output, where, as soon as it reaches 0.81, it suddenly starts adding more decimal places to the load? I know that I can just round to avoid this problem, but I was wondering why this is happening. An increment of 0.01 does not seem crazy.

 0.77
 0.78
 0.79
 0.8
 0.81
 0.820000000000001
 0.830000000000001
 0.840000000000001
 0.850000000000001
 0.860000000000001
 0.870000000000001
+5
source share
4 answers

Computers use binary representations. Not all floating point decimals have exact representations in binary notation, so some error may occur (actually this is a rounding difference). For the same reason, do not use floating point numbers for monetary values :

messed up recepit

( dailywtf)

- , sprintf, . :

  • ,

:

#!/usr/bin/perl
for ($i=0; $i <= 360*100; $i += 1) {
  printf "%.2f \n", $i/100;
}
+16

, 0,01 , 0,01 , .

() , Perl. - , Google.

. : C ( ) , , .


Kernighan & , " ", :

  • : " ; , , ".

:

  • 10 * 0,1 - 1,0

, .

, (IBM PowerPC) IEEE 754: 2008. Perl (, ), .

+7

, C, . C Perl - , . . Perl , C float double.

C:

    #include <stdio.h>

    int main() {
        double i;
        for(i=0;i<=1;i+=.01)  {
          printf("%.15f\n",i);
        } 
      }

:

    0.790000000000000
    0.800000000000000
    0.810000000000000
    0.820000000000001
    0.830000000000001
    0.840000000000001
    0.850000000000001

, C, , .

:

    0.000000000000000
    0.009999999776483 
    0.019999999552965
    0.029999999329448
    0.039999999105930
    0.050000000745058
    0.060000002384186
    0.070000000298023
    0.079999998211861
    0.089999996125698
    0.099999994039536
+4

1/10 is periodic in binary, just as 1/3 is periodic in decimal. Therefore, it cannot be accurately stored in a floating point number.

>perl -E"say sprintf '%.17f', 0.1"
0.10000000000000001

Or work with integers

for (0*100..360*100) {
   my $i = $_/100;
   print "$i ";
}

Or do a lot of rounding

for (my $i=0; $i <= 360; $i = sprintf('%.2f', $i + 0.01)) {
   print "$i ";
}
+2
source

All Articles