Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Converting 2**54-1 to Binary

by philiprbrenan (Monk)
on Mar 17, 2017 at 21:00 UTC ( [id://1185078]=perlquestion: print w/replies, xml ) Need Help??

philiprbrenan has asked for the wisdom of the Perl Monks concerning the following question:

require v5.16; use Test::More qw(no_plan); for(51..66) {my $s = sprintf("%b", 2**$_-1); ok length($s) == $_; }

gives me:

# Looks like you failed 12 tests of 16. ok 1 ok 2 ok 3 not ok 4 not ok 5 not ok 6 not ok 7 not ok 8 not ok 9 not ok 10 not ok 11 not ok 12 not ok 13 ok 14 not ok 15 not ok 16 1..16

Is this something to worry about?

Replies are listed 'Best First'.
Re: Converting 2**54-1 to Binary
by duelafn (Parson) on Mar 18, 2017 at 13:55 UTC

    And, to make it work as you were expecting, use Math::BigInt

    use 5.016; use Test::More qw(no_plan); use Math::BigInt; for (51..66) { # substr to remove 0b prefix my $s = substr(Math::BigInt->new("2")->bpow($_)->bdec->as_bin, 2); # Or: Math::BigInt->new("1")->blsft($_)->bdec->as_bin is length($s), $_, "1 << $_ -1"; } __END__ ok 1 - 1 << 51 -1 ok 2 - 1 << 52 -1 ok 3 - 1 << 53 -1 ok 4 - 1 << 54 -1 ok 5 - 1 << 55 -1 ok 6 - 1 << 56 -1 ok 7 - 1 << 57 -1 ok 8 - 1 << 58 -1 ok 9 - 1 << 59 -1 ok 10 - 1 << 60 -1 ok 11 - 1 << 61 -1 ok 12 - 1 << 62 -1 ok 13 - 1 << 63 -1 ok 14 - 1 << 64 -1 ok 15 - 1 << 65 -1 ok 16 - 1 << 66 -1 1..16

    Good Day,
        Dean

      Or Math::BigNum if one has a large number of calculations and needs a bit more speed.

      use 5.016; use Test::More qw(no_plan); use Math::BigNum; for (51..66) { # no need to substr to remove 0b prefix my $s = Math::BigNum->new(2)->bpow($_)->bdec->as_bin; is length($s), $_, "1 << $_ -1"; } __END__ ok 1 - 1 << 51 -1 ok 2 - 1 << 52 -1 ok 3 - 1 << 53 -1 ok 4 - 1 << 54 -1 ok 5 - 1 << 55 -1 ok 6 - 1 << 56 -1 ok 7 - 1 << 57 -1 ok 8 - 1 << 58 -1 ok 9 - 1 << 59 -1 ok 10 - 1 << 60 -1 ok 11 - 1 << 61 -1 ok 12 - 1 << 62 -1 ok 13 - 1 << 63 -1 ok 14 - 1 << 64 -1 ok 15 - 1 << 65 -1 ok 16 - 1 << 66 -1 1..16
Re: Converting 2**54-1 to Binary
by Eily (Monsignor) on Mar 17, 2017 at 21:17 UTC

    Try using 1 << 56 instead, ** works on floats, where precision (nb of significant digits) is lowered in favour of a wider range of values (very small or very big numbers are possible)

      Depends on the system: if you've got a 32-bit IV (perl -V:ivsize or perl -MConfig -le 'print $Config{ivsize}' will show 4 bytes for 32-bit, 8 bytes for 64-bit), then even that won't work, because it will overrun the 32-bit integer at 1<<32 - 1. And even with 64 bits, it will stop working above 64:

      require v5.16; use Test::More qw(no_plan); for(51..66) {my $s = sprintf("%b", 1 << $_ -1); is length($s), $_, "1 << $_ -1"; } __END__ ok 1 - (1 << 51) -1 ok 2 - (1 << 52) -1 ok 3 - (1 << 53) -1 ok 4 - (1 << 54) -1 ok 5 - (1 << 55) -1 ok 6 - (1 << 56) -1 ok 7 - (1 << 57) -1 ok 8 - (1 << 58) -1 ok 9 - (1 << 59) -1 ok 10 - (1 << 60) -1 ok 11 - (1 << 61) -1 ok 12 - (1 << 62) -1 ok 13 - (1 << 63) -1 ok 14 - (1 << 64) -1 not ok 15 - (1 << 65) -1 # Failed test '(1 << 65) -1' # at - line 6. # got: '64' # expected: '65' not ok 16 - (1 << 66) -1 # Failed test '(1 << 66) -1' # at - line 6. # got: '64' # expected: '66' 1..16 # Looks like you failed 2 tests of 16.

      So, philiprbrenan, "is this something to worry about?" depends on what you want to do. It's doing exactly what's expected for a double-float NV. And my example code does what's expected for a 64-bit integer. But as to whether that's behavior to worry about depends on what you're trying to do with your 2**$_n-1.

Re: Converting 2**54-1 to Binary
by stevieb (Canon) on Mar 17, 2017 at 21:33 UTC

    Perl 5.24.1 64-bit, for reference:

    use warnings; use strict; for(51..66){ my $s = sprintf("%b", 2**$_-1); print "$_:" . length($s) . "\n"; }

    Output (* denotation is added after the fact to represent where it starts to "break").:

    51:51 52:52 53:53 54:54 55:55 56:56 57:57 58:58 59:59 60:60 61:61 62:63 * 63:64 * 64:64 * 65:64 * 66:64 *
Re: Converting 2**54-1 to Binary
by ikegami (Patriarch) on Mar 20, 2017 at 02:33 UTC

    Double-precision floating point numbers have 53 bits of precision. 2**54-1 requires 54 bits of precision to represent, so it can't be represented exactly by a double-precision floating point number.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1185078]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-04-19 06:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found