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.
| [reply] [Watch: Dir/Any] [d/l] |
|
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.
| [reply] [Watch: Dir/Any] |
|
| [reply] [Watch: Dir/Any] [d/l] |
Re: bug in Perl compilation?
by duff (Parson) on Dec 21, 2005 at 18:44 UTC
|
$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.
| [reply] [Watch: Dir/Any] [d/l] |
|
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.
| [reply] [Watch: Dir/Any] |
|
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".
| [reply] [Watch: Dir/Any] |
Re: bug in Perl compilation?
by ikegami (Patriarch) on Dec 21, 2005 at 18:47 UTC
|
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).
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
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.
| [reply] [Watch: Dir/Any] |
|
| [reply] [Watch: Dir/Any] |
|
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)
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
|
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.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
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.
| [reply] [Watch: Dir/Any] |
|
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...
| [reply] [Watch: Dir/Any] |