Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

bug in Perl compilation?

by bkgallo (Initiate)
on Dec 21, 2005 at 18:31 UTC ( [id://518391]=perlquestion: print w/replies, xml ) Need Help??

bkgallo has asked for the wisdom of the Perl Monks concerning the following question:

Hello Masters,

On a Linux system I execute the following code:

-------------X Code Start X---------------
#!/usr/bin/perl -wT
 
$string1 = 12e-4;
$string2 = 1.2e-3;
 
if ( $string1 > $string2 ) {
  print "$string1 is greater than $string2\n";
}
elsif ( $string1 == $string2 ) {
  print "$string1 is equal to $string2\n";
}
else {
  print "$string1 is less than $string2\n";
}
--------------X Code End X----------------
The result I get is
0.0012 is less than 0.0012
After some testing, I've found that numbers in exponential notation with exponents in the range from "-1" to "-3" produce the same weird behavior. I do not get any such weird results on my HP-UX 11.00 system or my Win2K box. After reading through http://perldoc.perl.org/perlnumber.html, I'm wondering if this is due to losses of information in the conversion of data types because of limitations/features of the C compiler on the Linux system.

If any of you Masters has seen this issue, would you know how to either (1) account for this by adding Perl code or (2) recompile Perl on this Linux system using some other flags? FYI, I was not involved with the compiling of Perl on this system in any way.

Thanks for any help you all can provide.

Replies are listed 'Best First'.
Re: bug in Perl compilation?
by swampyankee (Parson) on Dec 21, 2005 at 19:52 UTC

    Similar comments have come up before. While I would consider the case the OP showed a bug -- more likely in the underlying C compiler than in the source code for Perl (see below) -- it is also fairly well known that floating point is, most emphatically, not isomorphic with real numbers. See, for some more information:

    What every computer scientist should know about floating-point arithme +tic Source ACM Computing Surveys (CSUR) archive Volume 23 , Issue 1 (March 1991) table of contents Pages: 5 - 48 Year of Publication: 1991 ISSN:0360-0300 Author David Goldberg Xerox Palo Alto Research Center, Palo Alto, CA

    The reason I would consider this behavior to be a bug is that it only occurs on one system. I'm blaming the C-compiler because I would expect the numerical processing code is among the least system-dependent parts of the Perl source.

      I also suspect it's a bug in the C compiler. So this begs the question of how to correct this situation. But first a clarifying question: does this behavior occur because the C compiler (which has the suspected bug in it) is accessed at runtime or was the bug "hardcoded" into Perl during Perl's compilation by this C compiler?

      If the behavior occurs only because the C compiler is accessed during runtime then it may be only a case of getting the latest C runtime compiler patch to correct this behavior.

      If the behavior occurs because the C compiler had a bug during Perl's compilation then either Perl will have to be recompiled (with an updated C compiler, of course) or a new Perl installation of previously compiled-for-Linux code will have to be installed.

        I also suspect it's a bug in the C compiler.

        No, by default, perl uses its own atof() implementation to convert strings to numbers instead of the one from libc. It is explained inside the perl.h file from the perl source.

Re: bug in Perl compilation?
by duff (Parson) on Dec 21, 2005 at 18:44 UTC

    Looks like your standard floating point inaccuracies to me. Try

    $num1 = 12e-4; $num2 = 1.2e-3; printf("%.18g\n", $num1); printf("%.18g\n", $num2);

    (Sorry, I can't call a scalar that's meant to hold a numeric value "string" anything)

    Remember that something somewhere has to do the computation to turn that scientific notation into a real number and that any computation involving floating point numbers is sure to have precision problems.

      duff,

      Here are the results of running your code.

      LINUX:

      0.00119999999999999989
      0.00120000000000000011
      HP-UX:
      0.0011999999999999999
      0.0011999999999999999
      WIN2K (with ActivePerl):
      0.0012
      0.0012

      Wow, how can the Linux system interpret the same number so differently? Something weird must be going on with whatever does the numerical conversion.

        Wow, how can the Linux system interpret the same number so differently?

        The difference between 0.00119999999999999989 and 0.00120000000000000011 isn't really that much, numerically. In fact, the difference is 0.00000000000000000022. I'm not sure if that really warrants a "wow".

Re: bug in Perl compilation?
by ikegami (Patriarch) on Dec 21, 2005 at 18:47 UTC

    I'm curious as to what

    perl -e 'printf("%.30f\n", $_) foreach 12e-4, 1.2e-3'

    prints for you. I get

    0.001199999999999999900000000000 0.001199999999999999900000000000

    on ActivePerl v5.6.1 on Win2k (where I get 0.0012 is equal to 0.0012).

      With perl v5.6.1 on WinXP (*not* ActivePerl), I get the same as you did.
      And the OP's code produces "0.0012 is equal to 0.0012" for me.
      LINUX:
      0.001199999999999999894875757356 0.001200000000000000111716191853
      HP-UX:
      0.001199999999999999890000000000 0.001199999999999999890000000000
      WIN2K (with ActivePerl):
      0.001200000000000000000000000000 0.001200000000000000000000000000

      Even weirder results than with duff's code.

      Anybody know any way to make this portable across all the platforms?

        That's so weird!! I thought this was all standardized.

        Anybody know any way to make this portable across all the platforms?

        When dealing with reals, you usually need to compare within a tolerance.
        a == b
        is equivalent to
        a - b == 0
        and to
        |a - b| <= 0
        With a tolerance, it becomes
        |a - b| <= tol

        Tolerance can be absolute
        (e.g. tol = 0.0001)
        or relative
        (e.g. tol = a * 0.05)

Re: bug in Perl compilation?
by blazar (Canon) on Dec 22, 2005 at 11:24 UTC

    To build on ikegami's reply, this is a faq. Check perldoc -q 'long decimals'.

    Said this, I recommend using <code> tags for your code. Also, as $Larry said, the shebang line is much like a "hello" and the __END__ token is much like a "bye", so they should be more than enough to visually mark the beginning and the end of your code.

      Thanks everyone for your help. I think I'll use the method mentioned in "perldoc -q 'long decimals'" to resolve this.

      But from an algorithmic perspective, it still irks me that these two numbers, which represent the exact same value, get converted to two slightly different binary values on this Linux system. I for one would call that a bug in the C compiler.

        Well, I don't have the slightest idea if it is actually a bug and if it is a bug of the C compiler or who knows what, but salva says it should not, and I don't know whether to trust him, but definitely he seems to be knowledgeable, certainly (much much) more than I am, so I'd take his word for the moment...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://518391]
Approved by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (4)
As of 2024-03-29 13:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found