in reply to Re^3: Variables are automatically rounded off in perl
in thread Variables are automatically rounded off in perl
Hi,
# In JavaScript, you can store 3335.9999999999995 which has 17 significant digits
Perl will actually store that number correctly, as this indicates:
Same goes for perl:
Yes - annoying, isn't it. Simplest way to see what a floating point value actually is, is to either:
For example:
(This has been addressed in the current github version.)
If you're using perl-5.28.x or earlier, then you also need to be aware that perl often assigns slightly incorrect values. (This is fixed in perl-5.29.4 and later, so long as $Config{d_strtod} is defined.)
If you want to be assured that a value is assigned correctly on perl-5.28 and earlier, simplest way might be (untested) to assign that value as a string provided to POSIX::strtod.
That is do:
I think this could be just 2 different languages making different choices regarding behaviour of the modulus operator when applied to fractional values.
Someone else might be able to provide more definitive advice about that.
Cheers
Rob
# In JavaScript, you can store 3335.9999999999995 which has 17 significant digits
Perl will actually store that number correctly, as this indicates:
The problem is that when perl prints these numbers out it first rounds them to 15 digits - hence perl prints out the same figure for each of the 2 values featured in the above one-liner, even though perl knows that the 2 values are different:C:\>perl -le "print 'ok' if 3335.9999999999995 > 3335.999999999999;" ok
# In JavaScript, if you try to add 3335.9999999999995 + 0.0000000000001, it is equal to 3335.9999999999995C:\>perl -le "print 3335.9999999999995; print 3335.999999999999;" 3336 3336
Same goes for perl:
Again, the problem is perl's commitment to outputting an approximation:C:>perl -le "print 'ok' if 3335.9999999999995 + 0.0000000000001 == 333 +5.9999999999995;" ok
# "print" won't display the last significant digitC:\>perl -le "print 3335.9999999999995;" 3336
Yes - annoying, isn't it. Simplest way to see what a floating point value actually is, is to either:
If you want to go to the trouble of installing Math::MPFR (which requires gmp and mpfr C libraries), I've just added an nvtoa() function which will return a string representation of an NV using as few digits as are necessary. (The nvtoa function requires mpfr-4.0.0 or later.)printf "%a", $float; or printf "%.16e", $float;
For example:
Works with __float128 and long double builds, too - though Math-MPFR-4.09 (latest CPAN release) is somewhat slower than it ought to be for these nvtypes when abs(exponent) > about 500.C:\>perl -MMath::MPFR=":mpfr" -le "print nvtoa(2 ** -1074);" 5e-324 C:\>perl -MMath::MPFR=":mpfr" -le "print nvtoa(sqrt 2.0);" 1.4142135623730951
(This has been addressed in the current github version.)
If you're using perl-5.28.x or earlier, then you also need to be aware that perl often assigns slightly incorrect values. (This is fixed in perl-5.29.4 and later, so long as $Config{d_strtod} is defined.)
If you want to be assured that a value is assigned correctly on perl-5.28 and earlier, simplest way might be (untested) to assign that value as a string provided to POSIX::strtod.
That is do:
instead of :use POSIX qw(strtod); $x = strtod('1234e-5');
Or, you can also use Math::MPFR:$x = 1234e-5;
# So, in order to get the same result you would get in JavaScript, you would call FMOD() function (see below) instead of using the % (mod) operatoruse Math::MPFR qw(:mpfr); $x = atonv('1234e-5');
I think this could be just 2 different languages making different choices regarding behaviour of the modulus operator when applied to fractional values.
Someone else might be able to provide more definitive advice about that.
Cheers
Rob
|
---|
Replies are listed 'Best First'. | |
---|---|
Re^5: Variables are automatically rounded off in perl
by syphilis (Archbishop) on Feb 11, 2019 at 11:23 UTC |
In Section
Seekers of Perl Wisdom