Math

I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
Robert Hicks
I realize that any math in Perl is probably slower than the same math
in "C" but I was wondering if Perl was as accurate as "C" in math
computations. I don't see why it wouldn't be but I thought I would ask
as a heavy spherical math project is on the horizon.

For some unfathomable reasons, Perl uses non-invertible transformations
between strings and numbers. So if your handling of numbers involves
converting them to strings, then back, the precision will be lost.

perldoc perlnumber

for details.

Hope this helps,
Ilya
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
Mirco Wahab
From my own experiences: Perl is not *that* slow in
numerical thinks.

The slowdown due to *literal* translation of a C program to a Perl
program is, in my experience, between 80x and 200x. Whether it is
tolerable depends in the usage pattern.

Hope this helps,
Ilya
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
Sisyphus
According to my Math::BigFloat (version 1.51) documentation you can, for
example:

use Math::BigFloat lib => 'GMP';

I do not know how it happens now, but some time ago the architecture
of Math::BigInt and Math::BigFloat modules was absolutely broken
performance-wise: AFAIK, instead of *delegating* the work to the
optimized modules, it creates *wrappers* about the optimized stuff.

Since the wrappers are written in Perl, the performance should suffer
a lot - unless you do calculations with madly big numbers (as in
crypto), so each "elementary operation" takes long enough to make
overhead of Perl wrappers is not crucial.
and that will, as I understand it, use the GMP integer routines instead of
the (pure perl) M::BI integer routines - so long as Math::BigInt::GMP has
been installed.

Hope this helps,
Ilya
 
M

Mirco Wahab

Ilya said:
[A complimentary Cc of this posting was sent to
Mirco Wahab
From my own experiences: Perl is not *that* slow in
numerical thinks.

The slowdown due to *literal* translation of a C program to a Perl
program is, in my experience, between 80x and 200x. Whether it is
tolerable depends in the usage pattern.

OK, if the program does depend *only* on
number crunching, the ratio I'd expect
would be around 1:100, as can also can
be seen from the numerical benchmarks
on http://shootout.alioth.debian.org,
eg. http://shootout.alioth.debian.org/debian/benchmark.php?test=nbody&lang=all
(planetary body movement simulation)
or http://shootout.alioth.debian.org/debian/benchmark.php?test=mandelbrot&lang=all
(mandelbrot set generation)

Thanks & regards

M.
 
S

Sisyphus

..
..
So if your handling of numbers involves
converting them to strings, then back, the precision will be lost.

It seems to me that you're saying that the following script will output
"Precision lost" (for some numeric value of $num, at least):

--------------------------
use warnings;
use strict;

my $num = 1.237e-6;
my $str = "$num";

if($num == $str) {print "Precision preserved\n"}
else {print "Precision lost\n"}
--------------------------

Do you have an example of such a value for $num ?

Cheers,
Rob
 
J

Jürgen Exner

Sisyphus said:
It seems to me that you're saying that the following script will
output "Precision lost" (for some numeric value of $num, at least):

--------------------------
my $num = 1.237e-6;
my $str = "$num";

if($num == $str) {print "Precision preserved\n"}
else {print "Precision lost\n"}

Oldest suspect in the world:
my $num = 1/3;
and the program above will print
Precision lost

jue
 
B

Brian Blackmore

Ilya Zakharevich said:
[A complimentary Cc of this posting was sent to
Robert Hicks
I realize that any math in Perl is probably slower than the same math
in "C" but I was wondering if Perl was as accurate as "C" in math
computations. I don't see why it wouldn't be but I thought I would ask
as a heavy spherical math project is on the horizon.
For some unfathomable reasons, Perl uses non-invertible transformations
between strings and numbers. So if your handling of numbers involves
converting them to strings, then back, the precision will be lost.

Yes, but I would question which programming languages don't suffer
from this behavior? As is mentioned by perlnumber, converting from
floating point to string is performed by the C compiler, whence Perl
is at the mercy of the system on which it was compiled. Moreover, I
must admit a bit of childish moronicity here in claiming that I know
of no language whatsoever that stores floats with infinite
precision, whence string conversion is always faulty.

If one uses a quotient field class, well then one is doing symbolic
algebra in one way shape or form, and again I wouldn't place blame
on the Perl numeric types.

Indeed, I was also thinking of something simple like 1/3, but have
you an example of a language where "1/3"=1/3? Or are there so many
that I'm just being dim?
 
M

Michele Dondi

Indeed, I was also thinking of something simple like 1/3, but have
you an example of a language where "1/3"=1/3? Or are there so many

Do you mean assignment to a constant string? ;-p


Michele
 
B

Brian Blackmore

Basically it has to do with the positions of ships. We get emails from
We currently have c libs with the math and a Perl/XS module that calls
those routines. We are having a horrible time moving that code from PA-
RISC to Itanium (the code is as old as IRIS and PRIME). So we may just
move it all into the Perl realm to make it easier going forward.
That sounds like a plan. You can do a lot of trigonometry per received
mail message, even in Perl, speed won't be a problem. There's
"Geo::Distance - Calculate Distances and Closest Locations" on CPAN.
GIS::Distance seems to be the aspiring successor.

I'll also add that I don't expect you to have any difficulty with
precision either, whether or not you're converting numbers to
strings and vice-versa. For instance, at fifteen digit precision,
one finds a change of one-one millionth of a second for epoch time,
leading to a 10^-9th change (degrees) in GHA Aries or Sol Azi.

Then again, taking the length of one degree of longitude at the
equator, fifteen digits of precision gives a direct error of 1nm, or
in other words, 10^-13 percent error. Indeed, rounding errors
propagate, etc., but that won't be as notable a problem than the
simple fact that you can't predict path one billion cycles ahead
anyway. Besides that, positioning information should probably not
be considered accurate to more than a meter anyway simply because of
common safety concerns, etc.

If you need to know the position of your ships to more precision
than one nanometer...
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
Brian Blackmore
Yes, but I would question which programming languages don't suffer
from this behavior?

What other programming languages with multi-representation numbers do
you know?
As is mentioned by perlnumber, converting from
floating point to string is performed by the C compiler,

Nope, by C RT libraries. And the for these libraries, they do it
following instructions from perl.
whence Perl is at the mercy of the system on which it was compiled.

And this the CHOICE made by perl. It could have done the conversion
itself.
Moreover, I must admit a bit of childish moronicity here in claiming
that I know of no language whatsoever that stores floats with
infinite precision, whence string conversion is always faulty.

I do not follow your usage of "whence", so cannot comment.
Indeed, I was also thinking of something simple like 1/3, but have
you an example of a language where "1/3"=1/3? Or are there so many
that I'm just being dim?

Yes. E.g., see

perl -MMath::pari=:int

Hope this helps,
Ilya
 
B

Brian Blackmore

Ilya Zakharevich said:
[A complimentary Cc of this posting was sent to
Brian Blackmore
Yes, but I would question which programming languages don't suffer
from this behavior?
What other programming languages with multi-representation numbers do
you know?

I thought we were talking about the classic `type conversion' issue.
Nope, by C RT libraries. And the for these libraries, they do it
following instructions from perl.

Following your advice, and checking perlnumber, what I found was what
I said up above:

"RESTRICTION: The conversions marked with "(*)" above
involve steps performed by the C compiler. In particular,
bugs/features of the compiler used may lead to breakage of
some of the above rules."

Since "native floating_point --> decimal string (*)" and
"decimal string --> native floating point (*)" are so marked, I
interpret that to mean that perl is at the whim of whatever C compiler
was used.
And this the CHOICE made by perl. It could have done the conversion
itself.

True, but that's a bit like saying that it's output could be based on
the TeX typesetting engine, that it's input stream should be entirely
XMLized and should natively handle images and gestured input, and that
it should natively translated any symbol set into the appropriate
characters necessary to create code.
I do not follow your usage of "whence", so cannot comment.

Lacking a programming language where float->string conversion is
invertible, converting to strings in any language creates a loss of
precision, which is no difficulty to imagine given a base ten
representation in a string in comparison to a base two representation
for a float.
Yes. E.g., see
perl -MMath::pari=:int

So perl has the ability after all, and doesn't use non-invertible
transforms, so there are no unfathomable reasons.

In any case, I don't find this a satisfactory example of a programming
language that avoids the concern in question. If anything, we've just
verified that arbitrary precision can doubtless be added to any Turing
complete language. That does not imply that Perl is any better or
worse than anything else in that regard.

Am I still missing the obvious examples of programming languages where
type casts are invertible without information loss?
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
Brian Blackmore
I thought we were talking about the classic `type conversion' issue.

If you mean *explicit* conversion from binary representation to string
and back, then ANY language I know can do it losslessly.
Following your advice, and checking perlnumber, what I found was what
I said up above:

"RESTRICTION: The conversions marked with "(*)" above
involve steps performed by the C compiler. In particular,
bugs/features of the compiler used may lead to breakage of
some of the above rules."

I wonder whether it is the original text (written by me); might be so.
It does not make any sense; the intent is clear, but the wording is
very bad... I tried to "keep things simple", but this error is not in
that category...
Since "native floating_point --> decimal string (*)" and
"decimal string --> native floating point (*)" are so marked, I
interpret that to mean that perl is at the whim of whatever C compiler
was used.

Yes - in the sense, that usually C compiler determines which CRTL is used.

What you are missing however, that even if Perl uses CRTL functions,
they take a lot of "options". And it is the options which Perl uses
which lead to precision loss.

AND, as I said, Perl could have used some specialized functions tuned
up to its problem domain (multi-representation).
True, but that's a bit like saying that it's output could be based on
the TeX typesetting engine, that it's input stream should be entirely
XMLized and should natively handle images and gestured input, and that
it should natively translated any symbol set into the appropriate
characters necessary to create code.

Sorry, I have no idea what was it you wanted to express here.
Lacking a programming language where float->string conversion is
invertible,

??? See above.
converting to strings in any language creates a loss of
precision, which is no difficulty to imagine given a base ten
representation in a string in comparison to a base two representation
for a float.



So perl has the ability after all, and doesn't use non-invertible
transforms, so there are no unfathomable reasons.

Again, the way I can parse this, it makes no sense.

Hope this helps,
Ilya
 
P

Peter J. Holzer

Yes, but I would question which programming languages don't suffer
from this behavior?

I don't know. Which does? C certainly doesn't (although specific
implementations might).
As is mentioned by perlnumber, converting from floating point to
string is performed by the C compiler, whence Perl is at the mercy of
the system on which it was compiled.

The glibc has no problem in this regard, AFAICT.
Moreover, I must admit a bit of childish moronicity here in claiming
that I know of no language whatsoever that stores floats with infinite
precision, whence string conversion is always faulty.

Nope. Converting a binary number of a given precision to decimal and
back to binary is always possible without loss[0]. The problem seems to
be that perl uses only 15 decimal digits, while it would need 16 to
cover the 53 bits of mantissa (I think 16 should be enough, but I
haven't considered all cases - maybe there are some where 17 are
required).

Indeed, I was also thinking of something simple like 1/3, but have
you an example of a language where "1/3"=1/3? Or are there so many
that I'm just being dim?

That's a completely different problem. 1/3 cannot be precisely
represented in binary, so the question whether it could be converted to
decimal and back is moot. The closest approximation to 1/3 which can be
represented in a 64 bit FP number
(0.333333333333333314829616256247390992939472198486328125) can be
converted to decimal and back without loss of precision.


hp


[0] In fact that's true for any two integral bases.
 
B

Brian Blackmore

Ilya Zakharevich said:
[A complimentary Cc of this posting was sent to
Brian Blackmore
Yes, but I would question which programming languages don't suffer
from this behavior?
What other programming languages with multi-representation numbers do
you know?

Yeah, I have to apologize here because I've conflated a couple of
ideas and caused a minor communication problem. Certainly the 1/3
issue is a matter of representation, whence a different issue, but I
brought that in from the other part of the thread. I think I've
been looking for a specific example to the first statement way up
above here, about losing precision during conversion. Is what you
had in mind something like this:

#!/usr/bin/perl

$a=42.1; for (1..30) { $a+=0.1 }
$b="$a"; print "a=",$a," b=",$b,"\n";
$a==$b ? print "Equal\n" : print "Not equal\n" ;
Nope, by C RT libraries. And the for these libraries, they do it
following instructions from perl.

I would like to know for future reference if this is in the manuals
or if I misinterpreted what's in perlnumber. Also, are these
instructions discussed anywhere, or just in the source? I'd like to
know exactly what's happening, so I can look at the sources, but it
might be nice to have this type of example in perlnumber.
And this the CHOICE made by perl. It could have done the conversion
itself.

Is it a choice of what parameters to pass to CRTL that is causing
the fault, or is it the choice to use the CRTL period? If it's a
parameter issue, why haven't the parameters been changed?
I do not follow your usage of "whence", so cannot comment.

Sorry, I conflated in the 1/3 example here.


Thanks all for the patience, and I hope we're not too far off topic,
but I just want to make sure I understand what actually is
unfathomable here and why, so I don't fall prey to these problems in
the future.
 
P

Peter J. Holzer

Peter J. Holzer said:
Nope. Converting a binary number of a given precision to decimal and
back to binary is always possible without loss[0]. The problem seems to
be that perl uses only 15 decimal digits, while it would need 16 to
cover the 53 bits of mantissa (I think 16 should be enough, but I
haven't considered all cases - maybe there are some where 17 are
required).
perl -Mbignum=a,100 -e 'my $numero=0; for (0..53) {$numero+= 1/2**$_}
;$numero =~ s/0*$//g;print length($numero)."\n$numero\n";'
55
1.99999999999999988897769753748434595763683319091796875

I'm not quite sure what you are trying to demonstrate here. That number
is not exactly representable in an IEEE-64bit-FP number (the mantissa is
one bit too long, afaics).

The nearest two numbers are

1.9999999999999997779553950749686919152736663818359375 and 2.0

1.9999999999999997779553950749686919152736663818359375 is adequately
represented by 1.9999999999999998, which indeed uses 17 digits in
decimal. So you have demonstrated that at least 17 decimal digits are
needed to represent 53 bits of mantissa. That answers my question -
thanks; but I would have preferred a more direct answer.

hp
 
B

Brian Blackmore

Brian Blackmore said:
Ilya Zakharevich said:
[A complimentary Cc of this posting was sent to
Brian Blackmore
For some unfathomable reasons, Perl uses non-invertible transformations
between strings and numbers. So if your handling of numbers involves
converting them to strings, then back, the precision will be lost.
Yes, but I would question which programming languages don't suffer
from this behavior?
What other programming languages with multi-representation numbers do
you know?
Yeah, I have to apologize here because I've conflated a couple of
ideas and caused a minor communication problem. Certainly the 1/3
issue is a matter of representation, whence a different issue, but I
brought that in from the other part of the thread. I think I've
been looking for a specific example to the first statement way up
above here, about losing precision during conversion. Is what you
had in mind something like this:

$a=42.1; for (1..30) { $a+=0.1 }
$b="$a"; print "a=",$a," b=",$b,"\n";
$a==$b ? print "Equal\n" : print "Not equal\n" ;


Sorry, I rescind my understanding because in C:

#include <stdio.h>
#include <stdlib.h>

int main() {
double a=42.1;
char* c;
double d;
int i=30;

for(;i>0;i--) { a+=0.1; }
sprintf(c,"%f",a);
d=atof(c);

printf("%f\n",a);
printf("%f\n",d);

if(a!=d) { printf("Lost precision\n"); }
else { printf("Okay\n"); }

return 0;
}


Both report on lost precision.

So now I'm back to being confused. When you speak of these
non-invertible transforms, is this what you had in mind? If so, it
doesn't seem to work on C either (contrary to a statement from
another person's post in this thread).

If this is not what you had in mind, can you give an example of Perl
going bad in the way you mentioned?

Thanks a bunch for your time.
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
Brian Blackmore
#!/usr/bin/perl

$a=42.1; for (1..30) { $a+=0.1 }
$b="$a"; print "a=",$a," b=",$b,"\n";
$a==$b ? print "Equal\n" : print "Not equal\n" ;



I would like to know for future reference if this is in the manuals
or if I misinterpreted what's in perlnumber.

I think we discussed this already. I might have oversimplified things
when I wrote perlnumber (or [hopefully ;-] it might have been a later edit).
Also, are these instructions discussed anywhere, or just in the
source?

Might be in the autogenerated POD for Configure variables:

perl -V:d_Gconvert

There is also perlvar for $#, but I suspect it is erroneous.
Is it a choice of what parameters to pass to CRTL that is causing
the fault, or is it the choice to use the CRTL period? If it's a
parameter issue, why haven't the parameters been changed?

There are two conflicting targets:

a) One does not want a silly semantic of number conversion (like
information loss);

b) One does not want to see silly bug reports like

why
perl -wle "$#='%.17g'; print 17.1"
prints garbage digits?

(I assume that this value of $# is the default, so setting it
would not appear in the bug report.)

c) The conversion should not be too slow.

With the current choice of $#, one STILL gets stuff as in "b". And
the precision is always always lost. But with finer $#, the bug
reports would be more frequent.

About mid-90s, there was a discussion about adding custom
stringification function, which does not has semantic of %.NNg, but
does better: it emits the minimal number of digits such that the
following conversion to a number would result in the initial number.
Somebody did a test, and found that using this custom function would
significantly slow down number-to-string conversion. So "c" was violate.

["a" would be fixed; it is not clear how this would change "b",
since fixing "a" increases number of cases where people would see
mismatch with "school arithmetic" (after performing arithmetic
operations on numbers with a few significant digits).]

However, a couple of years after this, I did some research, and found
out that perl was not caching results of number-to-string conversion.
After fixing it, the number of times perl calls number-to-string
conversion routines should have changed dramatically.

So it MIGHT be that using such a custom conversion function would not
violate "c". It also MIGHT be that it would not significantly
increase the flow of "b".

Choices, choices, choices - and shortage of time.

Hope this helps,
Ilya
 
P

Peter J. Holzer

$a after that is not 45.1. It is about 45.100000000000044.
Sorry, I rescind my understanding because in C:

#include <stdio.h>
#include <stdlib.h>

int main() {
double a=42.1;
char* c;
double d;
int i=30;

for(;i>0;i--) { a+=0.1; }
sprintf(c,"%f",a);
d=atof(c);

printf("%f\n",a);
printf("%f\n",d);

if(a!=d) { printf("Lost precision\n"); }
else { printf("Okay\n"); }

return 0;
}


Both report on lost precision.

For me it reports "segmentation fault (core dumped)" (well, actually the
shell reports that, the program dies before it can report anything). c
is used without being initialized.

The problem in your C program is that you are rounding a to six
fractional digits. Of course the number isn't the same when you round
it.

You need at least 16 or 17 for the 53 bits of mantissa (log10(2**53) ==
15.95). If you replace sprintf(c,"%f",a); with sprintf(c,"%.15f",a); (2
digits before the decimal point, 15 after is 17 digits total), the
program reports "Okay".

You can do the same in Perl of course. The problem in Perl is that Perl
does conversions between numeric and string values automatically and the
programmer may not be aware of it - so he may lose precision without
noticing it. In C you explicitely have to use (s)printf, and you
hopefully do think about possible loss of precision there.

hp
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top