http://qs321.pair.com?node_id=11123199


in reply to int() function

15/100 is periodic number in binary (0.00 1001 1001 1001 ...) just like 1/3 is periodic in decimal (0.333...) . As such, it can't accurately be stored as a floating point number since that would take infinite storage. The number you think you have isn't quite what you think it is.

$ perl -e'CORE::say sprintf("%.100f", 0.15) =~ s/0+\z//r' 0.1499999999999999944488848768742172978818416595458984375 $ perl -e'CORE::say sprintf("%.100f", (1.15*170)+0.50) =~ s/0+\z//r' 195.999999999999971578290569595992565155029296875
(Upd: syphilis points out %.100g naturally remove the trailing zeros.)

See What Every Programmer Should Know About Floating-Point Arithmetic. It covers how to handle this.

Replies are listed 'Best First'.
Re^2: int() function
by syphilis (Archbishop) on Oct 27, 2020 at 11:09 UTC
    Not that it's of great importance, but is there a reason that you've chosen to use "%.100f" formatting instead of "%.100g" formatting ?
    The "%.100g" formatting should remove any trailing zeros, thereby alleviating the need for the regex.

    I know that, on some systems, %g formatting can be buggy, but I don't know of any system where "%.100g" misbehaves && "%.100f" functions correctly.

    Cheers,
    Rob
      On my CentOS 7 box with perl-5.16.3
      $ perl -E'say sprintf("%.100g", 0.15)' 0.14999999999999999 $ perl -E'say sprintf("%.100f", 0.15)' 0.14999999999999999444888487687421729788184165954589843750000000000000 +00000000000000000000000000000000 $ perl --version | head -3 This is perl 5, version 16, subversion 3 (v5.16.3) built for x86_64-li +nux-thread-multi (with 40 registered patches, see perl -V for more detail)
      On my Fedora 32 box with perl-5.30.3
      $ perl -E'say sprintf("%.100g", 0.15)' 0.1499999999999999944488848768742172978818416595458984375 $ perl -E'say sprintf("%.100f", 0.15)' 0.14999999999999999444888487687421729788184165954589843750000000000000 +00000000000000000000000000000000 $ perl -E'say sprintf("%.100a", 0.15)' 0x1.333333333333300000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000p-3 $ perl -v|head -3 This is perl 5, version 30, subversion 3 (v5.30.3) built for x86_64-li +nux-thread-multi (with 96 registered patches, see perl -V for more detail)
        On my CentOS 7 box with perl-5.16.3

        That's certainly one instance where you do benefit from formatting with "%.100f" instead of "%.100g".
        Thank you for pointing this out.
        Turns out that it's the same on my Ubuntu box with perl-5.18.0.
        But with perl-5.32.0 on the same box, "%.100g" formatting works fine - so, there's a change in perl's behaviour between 5.18 and 5.32.
        I would guess that "%.100g" formatting on your CentOS 7 box would also work fine on perl-5.32.

        But I should point out that, even though "%.100g" formatting works ok on Ubuntu with perl-5.32.0, "%.*g" formatting is still buggy if you request a precision in the range 18..91 (inclusive).
        $ perl -le 'printf "%.91f\n", 0.15;' 0.14999999999999999444888487687421729788184165954589843750000000000000 +00000000000000000000000 $ perl -le 'printf "%.91g\n", 0.15;' 0.14999999999999999 $ perl -le 'printf "%.92g\n", 0.15;' 0.1499999999999999944488848768742172978818416595458984375
        Cheers,
        Rob

      No, it's simply an oversight.