Perl rounding error again

后端 未结 5 1004
野性不改
野性不改 2020-12-10 07:07

The example to show the problem:

  • having a number 105;
  • divide with 1000 (result 0.105)
  • rouded to 2 decimal places should be: 0.11
5条回答
  •  佛祖请我去吃肉
    2020-12-10 07:40

    In the old Integer math days of programming, we use to pretend to use decimal places:

    N = 345
    DISPLAY N        # Displays 345
    DISPLAY (1.2) N  # Displays 3.45
    

    We learned a valuable trick when attempting to round sales taxes correctly:

    my $amount = 1.344;
    my $amount_rounded = sprintf "%.2f", $amount + .005;
    my $amount2 = 1.345;
    my $amount_rounded2 = sprintf "%.2f", $amount2 + .005;
    say "$amount_rounted   $amount_rounded2";  # prints 1.34 and 1.35
    

    By adding in 1/2 of the precision, I display the rounding correctly. When the number is 1.344, adding .005 made it 1.349, and chopping off the last digit displays dip lays 1.344. When I do the same thing with 1.345, adding in .005 makes it 1.350 and removing the last digit displays it as 1.35.

    You could do this with a subroutine that will return the rounded amount.


    Interesting...

    There is a PerlFAQ on this subject. It recommends simply using printf to get the correct results:

    use strict;
    use warnings;
    use feature qw(say);
    
    my $number = .105;
    say "$number";
    printf "%.2f\n", $number;   # Prints .10 which is incorrect
    printf "%.2f\n", 3.1459;    # Prins 3.15 which is correct
    

    For Pi, this works, but not for .105. However:

    use strict;
    use warnings;
    use feature qw(say);
    
    my $number = .1051;
    say "$number";
    printf "%.2f\n", $number;   # Prints .11 which is correct
    printf "%.2f\n", 3.1459;    # Prints 3.15 which is correct
    

    This looks like an issue with the way Perl stores .105 internally. Probably something like .10499999999 which would be correctly rounded downwards. I also noticed that Perl warns me about using round and rounding as possible future reserved words.

提交回复
热议问题