Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

Re^3: Portability of floor(log(N))

by syphilis (Archbishop)
on Mar 13, 2018 at 22:50 UTC ( #1210855=note: print w/replies, xml ) Need Help??

in reply to Re^2: Portability of floor(log(N))
in thread Portability of floor(log(N))

Thank you for the suggestions.

I think they were completely irrelevant to the problem you're facing.
Silly me didn't think to actually check what the correct calculation of floor( log($num) / log(1000) ) should yield under 'long double' (64-bit) precision.

When I do check, I find that the correct answer is -12.
The error is in your test script ... either that, or in Math::MPFR:
use strict; use warnings; use Math::MPFR qw(:mpfr); # Set precision for extended # precision 'long double' Rmpfr_set_default_prec(64); my $num = Math::MPFR->new('1e-33'); my $thou = Math::MPFR->new('1000'); # Convert $num & $thou to their # respective log() Rmpfr_log($num, $num, MPFR_RNDN); Rmpfr_log($thou, $thou, MPFR_RNDN); print $num / $thou; # prints -1.10000000000000000009e1
This indicates that when the floating point precision is 64 bits, the correct floor() result is -12.
And, IIUC, the test script should accept '1000e-36' as correct when NV precision is 64 bits (as is the case with those 2 FAIL reports).

Interestingly, with full quad precision of 113 bits, the calculation reverts to returning -11.


Replies are listed 'Best First'.
Re^4: Portability of floor(log(N))
by syphilis (Archbishop) on Mar 14, 2018 at 02:42 UTC
    And, IIUC, the test script should accept '1000e-36' as correct when NV precision is 64 bits

    Alternatively (and since you're already using POSIX) you should get the result you expected, if you replace the log() calls with POSIX::log10(). That way both numerator and divisor should be exact (for these particular inputs), as should also be the result of the division ... irrespective of the precision of the NV:
    $ perl -MPOSIX -le 'print POSIX::floor(POSIX::log10(1e-33) / POSIX::lo +g10(1000));' -11
      Using POSIX::log10() looks like the simplest solution. I will attempt to pester the tester with a modified version of

      Do you think I can simplify it by replacing POSIX::log10(1000) with 3, or will it be better to keep your code as-is?

      my $e = floor( POSIX::log10($num) / 3 );

        log10(1000) will never change, and is exactly 3, so there's no reason not to use it

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1210855]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (2)
As of 2022-01-23 19:24 GMT
Find Nodes?
    Voting Booth?
    In 2022, my preferred method to securely store passwords is:

    Results (64 votes). Check out past polls.