Is this a bug?

Discussion in 'Ruby' started by Gerry Jenkins, Sep 20, 2010.

  1. for following version:
    ruby 1.9.1p129 (2009-05-12 revision 23412) [i386-darwin9.7.0]


    irb(main):002:0> sprintf("%.1f",-1.05)
    => "-1.1"
    irb(main):003:0> sprintf("%.1f",-32.05)
    => "-32.0"

    note the inconsistent rounding.

    -1.05 rounds to -1.1
    and
    -32.50 rounds to -32.0

    from sprintf
    --
    Posted via http://www.ruby-forum.com/.
     
    Gerry Jenkins, Sep 20, 2010
    #1
    1. Advertising

  2. > note the inconsistent rounding.
    >
    > -1.05 rounds to -1.1
    > and
    > -32.50 rounds to -32.0
    >
    > from =C2=A0sprintf



    For me it looks like you are rounding -32.05, not -32.50.

    > irb(main):003:0> sprintf("%.1f",-32.05)



    Regards, Rimantas
    --
    http://rimantas.com/
     
    Rimantas Liubertas, Sep 20, 2010
    #2
    1. Advertising

  3. Rimantas Liubertas wrote:
    >> note the inconsistent rounding.
    >>
    >> -1.05 rounds to -1.1
    >> and
    >> -32.50 rounds to -32.0
    >>
    >> from  sprintf

    >
    >
    > For me it looks like you are rounding -32.05, not -32.50.
    >
    >> irb(main):003:0> sprintf("%.1f",-32.05)

    >
    >
    > Regards, Rimantas


    Yes, I intend to round -32.05 to the nearest 1 decimal place not to a
    whole number. sprintf is suppose to round to the precision you specify.
    --
    Posted via http://www.ruby-forum.com/.
     
    Gerry Jenkins, Sep 20, 2010
    #3
  4. Gerry Jenkins wrote:
    > Rimantas Liubertas wrote:
    >>> note the inconsistent rounding.
    >>>
    >>> -1.05 rounds to -1.1
    >>> and
    >>> -32.50 rounds to -32.0
    >>>
    >>> from  sprintf

    >>
    >>
    >> For me it looks like you are rounding -32.05, not -32.50.
    >>
    >>> irb(main):003:0> sprintf("%.1f",-32.05)

    >>
    >>
    >> Regards, Rimantas

    >
    > Yes, I intend to round -32.05 to the nearest 1 decimal place not to a
    > whole number. sprintf is suppose to round to the precision you specify.


    OK also inconsistent:

    irb(main):007:0> sprintf("%.0f",-1.5)
    => "-2"
    irb(main):008:0> sprintf("%.0f",-10.5)
    => "-10"

    -1.5 rounds down to -2
    -10.5 rounds up to -10
    --
    Posted via http://www.ruby-forum.com/.
     
    Gerry Jenkins, Sep 20, 2010
    #4
  5. Gerry Jenkins wrote:
    > Gerry Jenkins wrote:
    >> Rimantas Liubertas wrote:
    >>>> note the inconsistent rounding.
    >>>>
    >>>> -1.05 rounds to -1.1
    >>>> and
    >>>> -32.50 rounds to -32.0
    >>>>
    >>>> from  sprintf
    >>>
    >>>
    >>> For me it looks like you are rounding -32.05, not -32.50.
    >>>
    >>>> irb(main):003:0> sprintf("%.1f",-32.05)
    >>>
    >>>
    >>> Regards, Rimantas

    >>
    >> Yes, I intend to round -32.05 to the nearest 1 decimal place not to a
    >> whole number. sprintf is suppose to round to the precision you specify.

    >
    > OK also inconsistent:
    >
    > irb(main):007:0> sprintf("%.0f",-1.5)
    > => "-2"
    > irb(main):008:0> sprintf("%.0f",-10.5)
    > => "-10"
    >
    > -1.5 rounds down to -2
    > -10.5 rounds up to -10


    fails even positive numbers:

    sprintf("%.0f",10.5)
    => "10"

    irb(main):013:0> sprintf("%.0f",11.5)
    => "12"

    --
    Posted via http://www.ruby-forum.com/.
     
    Gerry Jenkins, Sep 20, 2010
    #5
  6. Gerry Jenkins

    Ben Giddings Guest

    On Sep 20, 2010, at 18:00 , Gerry Jenkins wrote:
    >> OK also inconsistent:
    >>=20
    >> irb(main):007:0> sprintf("%.0f",-1.5)
    >> =3D> "-2"
    >> irb(main):008:0> sprintf("%.0f",-10.5)
    >> =3D> "-10"
    >>=20
    >> -1.5 rounds down to -2
    >> -10.5 rounds up to -10

    >=20
    > fails even positive numbers:
    >=20
    > sprintf("%.0f",10.5)
    > =3D> "10"
    >=20
    > irb(main):013:0> sprintf("%.0f",11.5)
    > =3D> "12"


    =
    http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conve=
    rsion_and_rounding

    "Rounding is used when the exact result of a floating-point operation =
    (or a conversion to floating-point format) would need more digits than =
    there are digits in the significand. There are several different =
    rounding schemes (or rounding modes). Historically, truncation was the =
    typical approach. Since the introduction of IEEE 754, the default method =
    (round to nearest, ties to even, sometimes called Banker's Rounding) is =
    more commonly used."

    As for the original issue, how numbers ending in 0.05 are rounded for =
    display with 1 digit after the decimal:

    It does seem "inconsistent", but it isn't wrong. Both 32.1 and 32.0 are =
    equally distant from 32.05. Internally, floating point numbers are =
    represented as binary digits, so 32.05 isn't *exactly* 32.05, but the =
    closest value that can be represented in binary, which will be ever so =
    slightly higher or lower.

    Try looking at the numbers with more decimal points and you'll see what =
    I mean:

    irb(main):043:0> sprintf("%.1f",-29.05)
    =3D> "-29.1"
    irb(main):044:0> sprintf("%.1f",-30.05)
    =3D> "-30.1"
    irb(main):045:0> sprintf("%.1f",-31.05)
    =3D> "-31.1"
    irb(main):046:0> sprintf("%.1f",-32.05)
    =3D> "-32.0"
    irb(main):047:0> sprintf("%.1f",-33.05)
    =3D> "-33.0"
    irb(main):048:0> sprintf("%.1f",-34.05)
    =3D> "-34.0"
    irb(main):049:0> sprintf("%.20f",-29.05)
    =3D> "-29.05000000000000071054"
    irb(main):050:0> sprintf("%.20f",-30.05)
    =3D> "-30.05000000000000071054"
    irb(main):051:0> sprintf("%.20f",-31.05)
    =3D> "-31.05000000000000071054"
    irb(main):052:0> sprintf("%.20f",-32.05)
    =3D> "-32.04999999999999715783"
    irb(main):053:0> sprintf("%.20f",-33.05)
    =3D> "-33.04999999999999715783"
    irb(main):054:0> sprintf("%.20f",-34.05)
    =3D> "-34.04999999999999715783"

    So what it's rounding isn't the exact number you're typing in, but the =
    internal representation of that number in binary floating point format.

    There are ways of tweaking the math so that the rounding seems more =
    consistent, but no matter what, the values you enter won't be precisely =
    equal to that value when you're using floating point numbers.

    If you're not careful about rounding floating point digits, you can end =
    up with something like this:

    http://img.thedailywtf.com/images/200902/errord/DSC00669.JPG

    Ben
     
    Ben Giddings, Sep 20, 2010
    #6
  7. Thank you Ben,

    I did discover that there are various ways of rounding just before your
    reply at http://en.wikipedia.org/wiki/Rounding

    I am writing a ruby web based unit testing for my java students to
    submit their programs to.

    My real problem is that sprintf in ruby behaves differently in this
    regard to how java rounds.

    Oh well, I fixed it by creating unit test data that was within the
    precision of the final java output, so that rounding was not used in the
    unit testing.

    Ben Giddings wrote:
    > On Sep 20, 2010, at 18:00 , Gerry Jenkins wrote:
    >> fails even positive numbers:
    >>
    >> sprintf("%.0f",10.5)
    >> => "10"
    >>
    >> irb(main):013:0> sprintf("%.0f",11.5)
    >> => "12"

    >
    > http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding
    >
    > "Rounding is used when the exact result of a floating-point operation
    > (or a conversion to floating-point format) would need more digits than
    > there are digits in the significand. There are several different
    > rounding schemes (or rounding modes). Historically, truncation was the
    > typical approach. Since the introduction of IEEE 754, the default method
    > (round to nearest, ties to even, sometimes called Banker's Rounding) is
    > more commonly used."
    >
    > As for the original issue, how numbers ending in 0.05 are rounded for
    > display with 1 digit after the decimal:
    >
    > It does seem "inconsistent", but it isn't wrong. Both 32.1 and 32.0 are
    > equally distant from 32.05. Internally, floating point numbers are
    > represented as binary digits, so 32.05 isn't *exactly* 32.05, but the
    > closest value that can be represented in binary, which will be ever so
    > slightly higher or lower.
    >
    > Try looking at the numbers with more decimal points and you'll see what
    > I mean:
    >
    > irb(main):043:0> sprintf("%.1f",-29.05)
    > => "-29.1"
    > irb(main):044:0> sprintf("%.1f",-30.05)
    > => "-30.1"
    > irb(main):045:0> sprintf("%.1f",-31.05)
    > => "-31.1"
    > irb(main):046:0> sprintf("%.1f",-32.05)
    > => "-32.0"
    > irb(main):047:0> sprintf("%.1f",-33.05)
    > => "-33.0"
    > irb(main):048:0> sprintf("%.1f",-34.05)
    > => "-34.0"
    > irb(main):049:0> sprintf("%.20f",-29.05)
    > => "-29.05000000000000071054"
    > irb(main):050:0> sprintf("%.20f",-30.05)
    > => "-30.05000000000000071054"
    > irb(main):051:0> sprintf("%.20f",-31.05)
    > => "-31.05000000000000071054"
    > irb(main):052:0> sprintf("%.20f",-32.05)
    > => "-32.04999999999999715783"
    > irb(main):053:0> sprintf("%.20f",-33.05)
    > => "-33.04999999999999715783"
    > irb(main):054:0> sprintf("%.20f",-34.05)
    > => "-34.04999999999999715783"
    >
    > So what it's rounding isn't the exact number you're typing in, but the
    > internal representation of that number in binary floating point format.
    >
    > There are ways of tweaking the math so that the rounding seems more
    > consistent, but no matter what, the values you enter won't be precisely
    > equal to that value when you're using floating point numbers.
    >
    > If you're not careful about rounding floating point digits, you can end
    > up with something like this:
    >
    > http://img.thedailywtf.com/images/200902/errord/DSC00669.JPG
    >
    > Ben


    --
    Posted via http://www.ruby-forum.com/.
     
    Gerry Jenkins, Sep 20, 2010
    #7
  8. On 21.09.2010 00:39, Gerry Jenkins wrote:

    > I did discover that there are various ways of rounding just before your
    > reply at http://en.wikipedia.org/wiki/Rounding
    >
    > I am writing a ruby web based unit testing for my java students to
    > submit their programs to.
    >
    > My real problem is that sprintf in ruby behaves differently in this
    > regard to how java rounds.


    Since you are coming from a Java background I guess you are aware that
    JUnit's TestCase uses a delta for equals comparisons of float and double:

    http://www.junit.org/junit/javadoc/3.8.1/junit/framework/Assert.html

    > Oh well, I fixed it by creating unit test data that was within the
    > precision of the final java output, so that rounding was not used in the
    > unit testing.


    The proper solution IMHO would be a comparison of numeric values (i.e.
    not of strings) that takes the delta into account much the same way as
    it's done in JUnit because there is also named mismatch between the
    binary internal representation and the decimal external representation
    that we humans love to use.

    Cheers

    robert

    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
     
    Robert Klemme, Sep 21, 2010
    #8
    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. John

    Re: BUG? OR NOT A BUG?

    John, Sep 20, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    574
  2. RedEye
    Replies:
    2
    Views:
    596
    Jason Kester
    Dec 13, 2005
  3. Michel Joly de Lotbiniere

    Bug Parade Bug 4953793

    Michel Joly de Lotbiniere, Nov 30, 2003, in forum: Java
    Replies:
    4
    Views:
    655
    Michel
    Dec 2, 2003
  4. DarkSpy
    Replies:
    4
    Views:
    899
    tom_usenet
    Jun 27, 2003
  5. Steve Holden
    Replies:
    1
    Views:
    409
    Behrang Dadsetan
    Jul 2, 2003
Loading...

Share This Page