Sprintf bug

Discussion in 'Ruby' started by jwesley, Nov 11, 2005.

  1. jwesley

    jwesley Guest

    I think I've found a bug in the sprintf function:

    D:\src\ruby>ruby -v
    ruby 1.8.2 (2004-12-25) [i386-mswin32]

    D:\src\ruby>irb
    irb(main):001:0> sprintf("%.1f", 123456789012345678.to_f)
    => "123456789012345680.0"
    irb(main):002:0> sprintf("%.1f", 123456789012345678.to_f).to_i
    => 123456789012345680

    Notice that that sprintf changed the value by an order of magnitude...

    Justin
    jwesley, Nov 11, 2005
    #1
    1. Advertising

  2. jwesley wrote:
    > I think I've found a bug in the sprintf function:
    >
    > D:\src\ruby>ruby -v
    > ruby 1.8.2 (2004-12-25) [i386-mswin32]
    >
    > D:\src\ruby>irb
    > irb(main):001:0> sprintf("%.1f", 123456789012345678.to_f)
    > => "123456789012345680.0"
    > irb(main):002:0> sprintf("%.1f", 123456789012345678.to_f).to_i
    > => 123456789012345680
    >
    > Notice that that sprintf changed the value by an order of magnitude...
    >
    > Justin
    >


    FP imprecision changed the value by 2.0:

    irb(main):008:0> orig = 123456789012345678
    => 123456789012345678
    irb(main):009:0> sprintf("%.1f", orig.to_f).to_i - orig
    => 2

    and:

    irb(main):012:0> orig - 2.0 == orig
    => true
    irb(main):013:0> orig + 2.0 == orig
    => true
    irb(main):014:0> orig.to_f.to_i - orig
    => 2

    It's not sprintf's fault.

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Nov 11, 2005
    #2
    1. Advertising

  3. jwesley wrote:
    > I think I've found a bug in the sprintf function:
    >
    > D:\src\ruby>ruby -v
    > ruby 1.8.2 (2004-12-25) [i386-mswin32]
    >
    > D:\src\ruby>irb
    > irb(main):001:0> sprintf("%.1f", 123456789012345678.to_f)
    > => "123456789012345680.0"
    > irb(main):002:0> sprintf("%.1f", 123456789012345678.to_f).to_i
    > => 123456789012345680
    >
    > Notice that that sprintf changed the value by an order of magnitude...
    >
    > Justin


    Nope, not a Ruby bug:

    /* Solaris 10 */
    #include <stdio.h>

    int main(){
    printf("%.1f\n", 123456789012345678.0);
    return 0;
    }

    djberge@~/programming/C-528>gcc -Wall -o printftest printftest.c
    djberge@~/programming/C-529>./printftest
    123456789012345680.0

    Regards,

    Dan
    Daniel Berger, Nov 11, 2005
    #3
  4. jwesley

    Rob Rypka Guest

    On 11/11/05, jwesley <> wrote:
    > irb(main):001:0> sprintf("%.1f", 123456789012345678.to_f)
    > =3D> "123456789012345680.0"
    > irb(main):002:0> sprintf("%.1f", 123456789012345678.to_f).to_i
    > =3D> 123456789012345680


    Two more helpless kittens, struck down before their prime.

    Please think of the kittens.

    --
    Rob
    Rob Rypka, Nov 11, 2005
    #4
  5. jwesley

    jwesley Guest

    You're right, it change the value by 2...
    jwesley, Nov 11, 2005
    #5
  6. jwesley

    jwesley Guest

    Is there a standard way to get a more precise floating point number?
    jwesley, Nov 11, 2005
    #6
  7. jwesley

    Guest

    Hi,

    At Sat, 12 Nov 2005 07:32:13 +0900,
    jwesley wrote in [ruby-talk:165361]:
    > Is there a standard way to get a more precise floating point number?


    BigDecimal might help you.

    --
    Nobu Nakada
    , Nov 11, 2005
    #7
  8. On Nov 11, 2005, at 22:32, jwesley wrote:

    > Is there a standard way to get a more precise floating point number?


    Short answer. BigDecimal: http://www.ruby-doc.org/stdlib/libdoc/
    bigdecimal/rdoc/index.html

    Longer rambling answer and reason why it's not a bug in anything,
    just a design choice: IEEE 754 double-precision (64-bit) floating
    point numbers use 12 bits for sign and exponent, and 52 bits for the
    significand. Therefore, the smallest integer that can't be exactly
    represented as a float is 2^53+1

    123456789012345678
    9007199254740992 (2^53 + 1)

    So the number used for the test is fairly obviously larger than that
    value, and there's going to be some sort of error if you flip it
    around and use it. Ferinstance:

    irb(main):008:0> (2**53 + 1)
    => 9007199254740993
    irb(main):009:0> (2**53 + 1).to_f.to_i
    => 9007199254740992

    And look at *this* consequence of the inaccuracy:

    irb(main):029:0> i = (2**53 - 1).to_f
    => 9.00719925474099e+15
    irb(main):030:0> while i < (2**53 + 2)
    irb(main):031:1> puts "#{i.to_i}"
    irb(main):032:1> i += 1.0
    irb(main):033:1> end
    9007199254740991
    9007199254740992
    9007199254740992
    9007199254740992
    ...

    Fun stuff, eh?

    It's also worth noting that depending on the hardware instruction,
    you can get different results for the same calculation. And since we
    don't program in assembly, you can get different results depending on
    the compiler, or potentially compiler options, while still being
    entirely consistent with the spec.

    matthew smillie
    Matthew Smillie, Nov 11, 2005
    #8
  9. jwesley

    Guest

    On Nov 11, 2005, at 6:58 PM, Matthew Smillie wrote:
    > On Nov 11, 2005, at 22:32, jwesley wrote:
    >> Is there a standard way to get a more precise floating point number?

    > Short answer. BigDecimal: http://www.ruby-doc.org/stdlib/libdoc/
    > bigdecimal/rdoc/index.html
    >


    I'd recommended the following document if you really want to know
    about floating point.
    And if you haven't read this document (or something like it) then you
    probably shouldn't
    be writing programs (well, any *serious* programs) using floating point.

    What Every Computer Scientist Should Know About Floating-Point
    Arithmetic
    http://docs.sun.com/source/806-3568/ncg_goldberg.html


    Gary Wright
    , Nov 12, 2005
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mark Hubbart

    sprintf bug in 1.9.0?

    Mark Hubbart, Feb 16, 2004, in forum: Ruby
    Replies:
    5
    Views:
    220
  2. Replies:
    4
    Views:
    186
    Leslie Viljoen
    Jul 29, 2006
  3. Wes Gamble

    Bug in sprintf?

    Wes Gamble, Aug 18, 2006, in forum: Ruby
    Replies:
    23
    Views:
    328
    Hal Fulton
    Aug 20, 2006
  4. Peter Szinek

    sprintf bug (?)

    Peter Szinek, Nov 11, 2006, in forum: Ruby
    Replies:
    8
    Views:
    177
    Bernard Kenik
    Nov 14, 2006
  5. Daniel DeLorme

    sprintf bug?

    Daniel DeLorme, Feb 1, 2008, in forum: Ruby
    Replies:
    1
    Views:
    92
    Robert Klemme
    Feb 1, 2008
Loading...

Share This Page