Bug of <= operator?

Discussion in 'Perl Misc' started by Haikun, Jun 9, 2006.

  1. Haikun

    Haikun Guest

    Dear folks,

    I'm not sure if this is a bug of the less than "<=" operator, but the
    following piece of code looks like a mystery to me.

    ==== code snippet start =============
    #!/usr/bin/perl -w

    use strict;
    use warnings;

    my $start = 0.001;
    my $step = 0.001;

    for( my $i=$start; $i <= 0.009; $i+=$step){
    print "$i\n";
    }
    ==== code snippet end ==============

    The output is
    0.001
    0.002
    0.003
    0.004
    0.005
    0.006
    0.007
    0.008

    and 0.009 is missing from the output. If I change "<=" in the for
    clause to "le", the output becomes expected.
    0.001
    0.002
    0.003
    0.004
    0.005
    0.006
    0.007
    0.008
    0.009

    I know this looks impossible. But if you take a try you'll see it. I'm
    using the latest perl 5.8.8 on Windows.

    Thanks,
    Haikun
     
    Haikun, Jun 9, 2006
    #1
    1. Advertising

  2. Haikun

    David Squire Guest

    Haikun wrote:
    > Dear folks,
    >
    > I'm not sure if this is a bug of the less than "<=" operator, but the
    > following piece of code looks like a mystery to me.


    Time to read the FAQ on the (necessarily approximate) binary floating
    point representation of decimal numbers. In Perl or any other language
    compiled to run on hardware based on binary representations.

    perldoc -q decimal

    Regards,

    DS


    >
    > ==== code snippet start =============
    > #!/usr/bin/perl -w
    >
    > use strict;
    > use warnings;
    >
    > my $start = 0.001;
    > my $step = 0.001;
    >
    > for( my $i=$start; $i <= 0.009; $i+=$step){
    > print "$i\n";
    > }
    > ==== code snippet end ==============
    >
    > The output is
    > 0.001
    > 0.002
    > 0.003
    > 0.004
    > 0.005
    > 0.006
    > 0.007
    > 0.008
    >
    > and 0.009 is missing from the output. If I change "<=" in the for
    > clause to "le", the output becomes expected.
    > 0.001
    > 0.002
    > 0.003
    > 0.004
    > 0.005
    > 0.006
    > 0.007
    > 0.008
    > 0.009
    >
    > I know this looks impossible. But if you take a try you'll see it. I'm
    > using the latest perl 5.8.8 on Windows.
    >
    > Thanks,
    > Haikun
    >
     
    David Squire, Jun 9, 2006
    #2
    1. Advertising

  3. Haikun wrote:
    >
    > I'm not sure if this is a bug of the less than "<=" operator, but the
    > following piece of code looks like a mystery to me.


    No, this is not a bug, that is the way that floating point numbers work on
    binary computers.


    John
    --
    use Perl;
    program
    fulfillment
     
    John W. Krahn, Jun 9, 2006
    #3
  4. Haikun

    David Squire Guest

    David Squire wrote:
    > Haikun wrote:
    >> Dear folks,
    >>
    >> I'm not sure if this is a bug of the less than "<=" operator, but the
    >> following piece of code looks like a mystery to me.

    >
    > Time to read the FAQ on the (necessarily approximate) binary floating
    > point representation of decimal numbers. In Perl or any other language
    > compiled to run on hardware based on binary representations.
    >
    > perldoc -q decimal
    >
    >>
    >> ==== code snippet start =============
    >> #!/usr/bin/perl -w
    >>
    >> use strict;
    >> use warnings;
    >>
    >> my $start = 0.001;
    >> my $step = 0.001;
    >>
    >> for( my $i=$start; $i <= 0.009; $i+=$step){
    >> print "$i\n";
    >> }
    >> ==== code snippet end ==============
    >>


    Perhaps this will help to convince:

    ----

    #!/usr/bin/perl
    use strict;
    use warnings;

    my $start = 0.001;
    my $step = 0.001;
    my $eps = 1e-10;

    my $count = 0;
    for( my $i=$start; $i <= 0.009 + $eps; $i+=$step){
    print "$i\n";
    $count++;
    print "\$count = $count\n";
    }

    ----

    Output:

    0.001
    $count = 1
    0.002
    $count = 2
    0.003
    $count = 3
    0.004
    $count = 4
    0.005
    $count = 5
    0.006
    $count = 6
    0.007
    $count = 7
    0.008
    $count = 8
    0.009
    $count = 9


    Regards,

    DS
     
    David Squire, Jun 9, 2006
    #4
  5. Haikun

    Haikun Guest

    I see. Thanks for the clarification. But then my (possibly irrelevant)
    questions is, why would "<=" and "le" exhibit different behavior?

    I know "le" is also used to do string comparison. But in this case, if
    I code

    for( my $i=$start; $i le 9e-03; $i+=$step){
    print "$i\n";
    }

    The output is still correct. I have never observed "le" to fail in this
    matter.

    Thanks,
    Haikun

    David Squire wrote:
    > David Squire wrote:
    > > Haikun wrote:
    > >> Dear folks,
    > >>
    > >> I'm not sure if this is a bug of the less than "<=" operator, but the
    > >> following piece of code looks like a mystery to me.

    > >
    > > Time to read the FAQ on the (necessarily approximate) binary floating
    > > point representation of decimal numbers. In Perl or any other language
    > > compiled to run on hardware based on binary representations.
    > >
    > > perldoc -q decimal
    > >
    > >>
    > >> ==== code snippet start =============
    > >> #!/usr/bin/perl -w
    > >>
    > >> use strict;
    > >> use warnings;
    > >>
    > >> my $start = 0.001;
    > >> my $step = 0.001;
    > >>
    > >> for( my $i=$start; $i <= 0.009; $i+=$step){
    > >> print "$i\n";
    > >> }
    > >> ==== code snippet end ==============
    > >>

    >
    > Perhaps this will help to convince:
    >
    > ----
    >
    > #!/usr/bin/perl
    > use strict;
    > use warnings;
    >
    > my $start = 0.001;
    > my $step = 0.001;
    > my $eps = 1e-10;
    >
    > my $count = 0;
    > for( my $i=$start; $i <= 0.009 + $eps; $i+=$step){
    > print "$i\n";
    > $count++;
    > print "\$count = $count\n";
    > }
    >
    > ----
    >
    > Output:
    >
    > 0.001
    > $count = 1
    > 0.002
    > $count = 2
    > 0.003
    > $count = 3
    > 0.004
    > $count = 4
    > 0.005
    > $count = 5
    > 0.006
    > $count = 6
    > 0.007
    > $count = 7
    > 0.008
    > $count = 8
    > 0.009
    > $count = 9
    >
    >
    > Regards,
    >
    > DS
     
    Haikun, Jun 9, 2006
    #5
  6. Haikun

    David Squire Guest

    Haikun wrote:

    [top-posting corrected. Please don't do that. See the posting guidelines
    for this group]

    >
    > David Squire wrote:
    >> David Squire wrote:
    >>> Haikun wrote:
    >>>> Dear folks,
    >>>>
    >>>> I'm not sure if this is a bug of the less than "<=" operator, but the
    >>>> following piece of code looks like a mystery to me.
    >>> Time to read the FAQ on the (necessarily approximate) binary floating
    >>> point representation of decimal numbers. In Perl or any other language
    >>> compiled to run on hardware based on binary representations.
    >>>
    >>> perldoc -q decimal
    >>>
    >>>> ==== code snippet start =============
    >>>> #!/usr/bin/perl -w
    >>>>
    >>>> use strict;
    >>>> use warnings;
    >>>>
    >>>> my $start = 0.001;
    >>>> my $step = 0.001;
    >>>>
    >>>> for( my $i=$start; $i <= 0.009; $i+=$step){
    >>>> print "$i\n";
    >>>> }
    >>>> ==== code snippet end ==============
    >>>>

    >> Perhaps this will help to convince:
    >>
    >> ----
    >>
    >> #!/usr/bin/perl
    >> use strict;
    >> use warnings;
    >>
    >> my $start = 0.001;
    >> my $step = 0.001;
    >> my $eps = 1e-10;
    >>
    >> my $count = 0;
    >> for( my $i=$start; $i <= 0.009 + $eps; $i+=$step){
    >> print "$i\n";
    >> $count++;
    >> print "\$count = $count\n";
    >> }
    >>


    > I see. Thanks for the clarification. But then my (possibly irrelevant)
    > questions is, why would "<=" and "le" exhibit different behavior?
    >
    > I know "le" is also used to do string comparison. But in this case, if
    > I code
    >
    > for( my $i=$start; $i le 9e-03; $i+=$step){
    > print "$i\n";
    > }
    >
    > The output is still correct. I have never observed "le" to fail in this
    > matter.


    Here's one that does:

    ----

    #!/usr/bin/perl
    use strict;
    use warnings;

    for(my $i = 0; $i le 10; $i++){
    print "$i\n";
    }

    ----

    Output:

    ----

    0
    1

    ----

    Think about the string ordering of the numbers of your example. It works
    by coincidence.

    DS
     
    David Squire, Jun 10, 2006
    #6
    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. Jakob Bieling

    Q: operator void* or operator bool?

    Jakob Bieling, Mar 5, 2004, in forum: C++
    Replies:
    2
    Views:
    586
    Rob Williscroft
    Mar 5, 2004
  2. John Smith
    Replies:
    2
    Views:
    423
    Ivan Vecerina
    Oct 6, 2004
  3. Alex Vinokur
    Replies:
    4
    Views:
    3,051
    Peter Koch Larsen
    Nov 26, 2004
  4. Alex Vinokur
    Replies:
    3
    Views:
    5,029
    Jeff Schwab
    Mar 20, 2005
  5. Tim Clacy
    Replies:
    15
    Views:
    2,689
    Kanenas
    May 30, 2005
Loading...

Share This Page