Why is Perl inconsistent with sprintf rounding?

前端 未结 2 2030
执笔经年
执笔经年 2021-02-20 02:20

Here is a Perl script:

#!/usr/bin/perl

use strict;
use warnings;
use feature \'say\';

my @numbers = qw(
    0.254
    0.255
    0.256
);

foreach my $number (@         


        
相关标签:
2条回答
  • 2021-02-20 02:48

    Perl uses the underlying C library for formatting. What this library does may vary from platform to platform. Even POSIX says "The low-order digit shall be rounded in an implementation-defined manner."

    In glibc, which arguably is used by the majority of perl binaries out there, the behavior you see will be affected by a couple of things:

    First, as pointed out in another answer, the value you think is being rounded may not be exactly representable in floating point, and which way the rounding goes will be determined by if it is the next higher or lower representable number.

    Second, even if the value is exactly representable as halfway between two possible roundings, glibc will use banker's rounding. That is, it will round to an even digit. So sprintf '%.1g', .25 will produce .2, but sprintf '%.1g', .75 will produce .8.

    The quote from the Perl Cookbook is just plain wrong.

    0 讨论(0)
  • 2021-02-20 03:11

    If you add this line:

    $number = sprintf '%.15f', $number;
    

    before printing, you will have:

    0.254000000000000 => 0.25
    0.255000000000000 => 0.26
    0.256000000000000 => 0.26
    100.254000000000005 => 100.25
    100.254999999999995 => 100.25
    100.256000000000000 => 100.26
    

    as you can see, 100.255 is not exactly 100.255 this is due to representation of float numbers.

    0 讨论(0)
提交回复
热议问题