Re: Efficiently working with huge exponents
by syphilis (Archbishop) on Mar 20, 2015 at 13:34 UTC
|
I'd go straight to Math::MPFR (which uses the mpfr library, which in turn uses the gmp library).
However, in doing so I'm plugging one of my own modules - which perhaps lessens the value of my advice.
Anyway, on my Windows box:
C:\_32>perl -MMath::MPFR=":mpfr" -le "Rmpfr_set_default_prec(1024001);
+$x = Math::MPFR->new(2); $x **= 1024000; print $x;" >out.txt
The output file reveals:
5.194693363199925.....490149376e308254
The result is instant (maybe a quarter of a second).
The length of the string that is output correlates nicely to yours. It is 308263, which is 308255 + 1 (for the decimal point) + 7 (for the "e308254").
Do we also agree on the value ?
Maximum precision for my mpfr library (and hence for my Math::MPFR) is 1073741823 bits.
Update: Just noticed that the OP now specifies that full precision is not required:
perl -MMath::MPFR=:mpfr -le "Rmpfr_set_default_prec(28);print Math::MP
+FR->new(2) ** 1024000;"
5.194693363e308254
Cheers, Rob | [reply] [d/l] [select] |
Re: Efficiently working with huge exponents
by RichardK (Parson) on Mar 20, 2015 at 12:46 UTC
|
use Math::BigFloat lib => 'GMP';
AFIACT that calls Math::BigInt::GMP so you'll need to install that too.
use Math::BigInt;
# or make it faster with huge numbers: install (optional)
# Math::BigInt::GMP and always use (it will fall back to
# pure Perl if the GMP library is not installed):
# (See also the L<MATH LIBRARY> section!)
# will warn if Math::BigInt::GMP cannot be found
use Math::BigInt lib => 'GMP';
| [reply] [d/l] [select] |
Re: Efficiently working with huge exponents
by LanX (Saint) on Mar 20, 2015 at 12:19 UTC
|
| [reply] |
Re: Efficiently working with huge exponents
by Ea (Chaplain) on Mar 20, 2015 at 12:11 UTC
|
| [reply] |
|
I thought of this as well, but I still need to be able to perform other arithmetic operations on the result, such as addition, multiplication, and even further exponentiation. Plus if I do $n->blog(10) to get the base-10 exponent, I still have to wait out the 3-minute calculation of $n in the first place, or maybe there's some clever math that I learned too many decades ago that would help. :-)
| [reply] [d/l] [select] |
Re: Efficiently working with huge exponents (approx)
by tye (Sage) on Mar 20, 2015 at 13:39 UTC
|
| [reply] |
Re: Efficiently working with huge exponents
by Laurent_R (Canon) on Mar 20, 2015 at 16:19 UTC
|
Just a quick calculation in a one-liner:
$ time perl -E 'my $c = log(2) * 1024000; my $d = $c / log(1e100);
> $d = int $d; say $d; $c = $c - log(1e100) for 1..$d;
> say $c; say "Value is: ", exp $c, " x 1e${d}00";'
3082
125.987232628425
Value is: 5.19469341155068e+54 x 1e308200
real 0m0.039s
user 0m0.030s
sys 0m0.000s
The last decimals are certainly wrong, but it seems that we can say that 5.194693e+308254 is a fair approximation, obtained in 39 milliseconds.
Update (at 16:36 UTC): A better version of more or less the same:
$ time perl -E 'my $c = log(2) * 1024000; my $d = int ( $c / log(1e10
+0));
> say $d; $c = $c - $d * log(1e100);
> say $c; say "Value is: ", exp $c, " x 1e${d}00";'
3082
125.987232618965
Value is: 5.19469336241126e+54 x 1e308200
real 0m0.036s
user 0m0.000s
sys 0m0.046s
Update 2: fixed a wrong print out of the value.
| [reply] [d/l] [select] |
|
$ time perl -MMath::BigApprox=c -le'print c(2)**1024000'
5.194693e+308254
real 0m0.021s
user 0m0.012s
sys 0m0.004s
And it makes a good guess at how many decimal places to show as well.
| [reply] [d/l] |
|
| [reply] |
|
|
| [reply] |
|
|
Re: Efficiently working with huge exponents
by BrowserUk (Patriarch) on Mar 20, 2015 at 15:21 UTC
|
| [reply] |
|
The point I was getting at is that 2**1024000, is already logarithmic. Ie. 1024000 is log2 of your number.
Thus, to convert it to log10(), you only need divide it by log2( 10 ).
Then all you need is:
sub log2{ log( $_[0] ) / log( 2 ) }
sub log2ToLog10{ $_[0] / log2( 10 ) }
print log2ToLog10( 1024000 );;
308254.715559917
And once you have that, displaying it in human readable form becomes: my $log10 = log2ToLog10( 1024000 );
printf "%.16fe%d\n", 10**( $log10 - int( $log10 )), int( $log10 );;
5.1946933632179482e308254
Which is pretty accurate according to wolfram/alpha:
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
| [reply] [d/l] [select] |
|
A good observation and valid question, but, no, my calculations are not all powers of 2. Thanks for the math reminder. :-)
| [reply] |
|
|