in reply to Re: [s]printf %d oddity
in thread [s]printf %d oddity

I'd love to see an explanation for this. It's got me doubting Perl as a language for doing even simple calculations. I can't see how this can be put down to rounding errors between binary and decimal

Replies are listed 'Best First'.
Re^3: [s]printf %d oddity
by Joost (Canon) on May 20, 2005 at 09:45 UTC
    This is *just* what happens when you convert between binary and decimal - see the links I provided in the post below.

    update:
    Think of it like this: decimal floats are inaccurate too, since they can't represent a rational number like 1/3 in finite notation:

    1/3 = 0.333333333333333333....

    If all arithmatic was done using decimal notation, assuming a maximum of 10 places you get:

    $x = 1/3; # 0.3333333333 $y = $x * 3; $y == 1 -> false # $y == 0.9999999999

    The same thing happens here, only since humans have a hard time thinking in floating binary, it's much harder to predict where.

      Ok, well since I've had to do most of my financial calculations in PL/SQL in the past since I was dealing with Oracle Financials, I thought I'd try it out:
      create or replace function test return varchar2 as begin if (8.78 * 100 = 878) then return 'ok'; end if; return 'not ok'; end; /
      SQL> select test from dual; TEST ------------------------------------------------------------------- ok
      They're dealing with binary and decimal conversions. Now granted, I've had to deal with rounding errors in the past, but not for trivial calculations like the one above. I still contend that in this example, where we're not dealing with repeating numbers, that a language should be able to get it right
        Sure it would be nice if this would always work, but that's why it's recommended to always use sprintf() to round before comparing if you're working with floating point numbers. You won't know when it will break otherwise. Keep in mind that perl uses the underlying C compiler's native float.

        By the way, how do you know that 8.78 isn a repeating finite number in binary?

        On my machine:

        #!/usr/local/bin/perl -w use strict; my $x = pack("F",8.78); print(unpack("B*",$x)); __OUTPUT__ 1000111111000010111101010010100001011100100011110010000101000000

        Now, if I only knew which part was what :-)

        updated: s/8.98/8.78/

        Trivial? That would be some assembler