How to print (2 & (1 * (2**32)))?

P

Paul Lalli

sonet said:
print (2 & (1 * (2**32)));

The result is 2 ??

You're likely to get a much more informative response if you explain
why you think it should be something other than 2.

Paul Lalli
 
S

sonet

(2 & (1 * (2**32))) must be 0 ??

Paul Lalli said:
You're likely to get a much more informative response if you explain
why you think it should be something other than 2.

Paul Lalli
 
S

Sisyphus

Paul Lalli said:
You're likely to get a much more informative response if you explain
why you think it should be something other than 2.

Admittedly it's not a very well phrased question - but it doesn't surprise
me that someone should find that result surprising.

'perldoc perlop' says that Binary "&" returns its operands ANDed together
bit by bit. On the basis of that, it's hard to see how
100000000000000000000000000000000
&
000000000000000000000000000000010
is going to return anything other than 0. I assume there's an explanation
somewhere in the perl docs - but I couldn't find it.

Cheers,
Rob
 
P

Paul Lalli

Sisyphus said:
Admittedly it's not a very well phrased question - but it doesn't surprise
me that someone should find that result surprising.

'perldoc perlop' says that Binary "&" returns its operands ANDed together
bit by bit. On the basis of that, it's hard to see how
100000000000000000000000000000000
&
000000000000000000000000000000010
is going to return anything other than 0. I assume there's an explanation
somewhere in the perl docs - but I couldn't find it.

Does this help explain?
$ perl -le'printf ("%b\n", 2**32)'
11111111111111111111111111111111

On a 32 bit system, the biggest number that can be expressed is 2**32 -
1. Your buffer doth flow over. ;-)

Paul Lalli
 
P

Paul Lalli

David said:
sonet, mié20051228@11:06:40(CET):

Of course. '2 & anything' will yield 2 for any even 'anything', and 0 for
any odd 'anything'. See perlop.

Uhm. What part of perlop makes that mistake?

$ perl -le'print (2 & 8)'
0

I think you're thinking of the rule that
$x & 1 == 1 if $x is odd
$x & 1 == 0 if $x is even

No such similar rule applies for &-ing to 2.

Paul Lalli
 
T

takarov2003

Sisyphus said:
Admittedly it's not a very well phrased question - but it doesn't surprise
me that someone should find that result surprising.

'perldoc perlop' says that Binary "&" returns its operands ANDed together
bit by bit. On the basis of that, it's hard to see how
100000000000000000000000000000000
&
000000000000000000000000000000010
is going to return anything other than 0. I assume there's an explanation
somewhere in the perl docs - but I couldn't find it.

Probably because 2**32 comes out as -1:

#!/usr/bin/perl
use warnings;

print '(2 & (1 * (2**32)))', "\n";

$two = 2;
$two_power = 2**32;

#!/usr/bin/perl
use warnings;

print '(2 & (1 * (2**32)))', "\n";

$two = 2;
$two_power = 2**32;

$two_anded = $two & $two_power;

printf "(2 & (1 * (2**32))) = %d\n", (2 & (1 * (2**32)));
printf "%d \& %d \= %d\n",$two, $two_power, $two_anded;
==============================================

(2 & (1 * (2**32)))
(2 & (1 * (2**32))) = 2
2 & -1 = 2
 
E

Eric J. Roode

Does this help explain?
$ perl -le'printf ("%b\n", 2**32)'
11111111111111111111111111111111

On a 32 bit system, the biggest number that can be expressed is 2**32
- 1. Your buffer doth flow over. ;-)

Why would the buffer overflow? I thought if you did arithmetic that was
too big to fit into an integer, perl automagically promoted the number to a
floating-point. I would have guessed that, with %b, you'd get a binary
representation of the floating-point number. Apparently, however, when you
try to %b (or %d) a number greater than 2**32-1, you get -1.

Perl must internally be detecting that the floating-point number is too
large, and substituting -1 in that case.

--
Eric
`$=`;$_=\%!;($_)=/(.)/;$==++$|;($.,$/,$,,$\,$",$;,$^,$#,$~,$*,$:,@%)=(
$!=~/(.)(.).(.)(.)(.)(.)..(.)(.)(.)..(.)......(.)/,$"),$=++;$.++;$.++;
$_++;$_++;($_,$\,$,)=($~.$"."$;$/$%[$?]$_$\$,$:$%[$?]",$"&$~,$#,);$,++
;$,++;$^|=$";`$_$\$,$/$:$;$~$*$%[$?]$.$~$*${#}$%[$?]$;$\$"$^$~$*.>&$=`
 
P

Paul Lalli

Eric said:
I would have guessed that, with %b, you'd get a binary
representation of the floating-point number. Apparently, however, when you
try to %b (or %d) a number greater than 2**32-1, you get -1.

Perl must internally be detecting that the floating-point number is too
large, and substituting -1 in that case.

$ perl -le'printf ("%b\n", 4.5)'
100
$ perl -le'printf ("%b\n", 3.2)'
11

It would seem that %b truncates to an integer, just as %d, %o, and %x
do. This makes sense, as `perldoc -f sprintf` tells us this about the
%b format code:
%b an unsigned integer, in binary

Additionally, as relates to the original point of the & operator,
`perldoc perlop` tells us:
Used on numbers, the bitwise operators ("&", "|", "^", "~",
"<<", and ">>") always produce integral results.

Paul Lalli
 
B

Bill Ricker N1VUX

Does this help explain?
$ perl -le'printf ("%b\n", 2**32)'
11111111111111111111111111111111
On a 32 bit system, the biggest number that can be expressed is 2**32 -
1. Your buffer doth flow over. ;-)

And on a 64bit system ... or a 64bit Perl running on a 32 bit system! ... you
get the desired response -

$ perl -v | perl -nle 'print if /is perl,/i'
This is perl, v5.8.7 built for cygwin-thread-multi-64int
$ perl -w -e 'printf ("%b\n", 2**32);'
100000000000000000000000000000000
$ perl -w -e 'print (2 & (1 * (2**32)));'
0

Same system, other Perl says
D:\>perl -v | perl -nle "print if /is perl,/i"
This is perl, v5.6.0 built for MSWin32-x86-multi-thread
D:\>perl -w -e "printf(qq{%b\n}, 2**32)"
11111111111111111111111111111111
D:\>perl -w -e "print (2 & (1 * (2**32)));"
2

Real 64-bit hardware ...
$ perl -v | perl -nle 'print if /is perl,/i'
This is perl, v5.8.4 built for alpha-linux-thread-multi
$ perl -w -e 'printf ("%b\n", 2**32);'
100000000000000000000000000000000
$ perl -w -le 'print (2 & (1 * (2**32)));'
0


A Piii server running Ubuntu ...
$ perl -v | perl -nle 'print if /is perl,/i'
This is perl, v5.8.7 built for i486-linux-gnu-thread-multi
$ perl -w -e 'printf ("%b\n", 2**32);'
11111111111111111111111111111111
$ perl -w -le 'print (2 & (1 * (2**32)));'
2

Thank you for this question, I didn't know Cygwin's perl for their Gnu-on-Win
was 64 bit before I checked this behavior. I'm not sure how the Cygwin folks
got their Perl distribution to compile 64bit for 686 architecture, but I'm not
complaining. It also has USE_LARGE_FILES so maybe I can scan the 4MB
dictionary file now ...

Happy Holiday,

Bill
http://use.perl.org/~n1vux
I had a .sig before the Eternal September ... what's the point now?
 
S

Sisyphus

"Paul Lalli" <[email protected]>
..
..
Does this help explain?
$ perl -le'printf ("%b\n", 2**32)'
11111111111111111111111111111111

You get the same for 2 ** 33 (and larger powers). Is this reliable, defined
behaviour ? Or is it machine dependent ? Or is it just plain undefined
behaviour ? I'm a little curious as to where the documentation is.
On a 32 bit system, the biggest number that can be expressed is 2**32 -
1. Your buffer doth flow over. ;-)

Yes - but shouldn't this be spelled out clearly in the perl docs ? (I would
think it *is* spelled out clearly in the perl documentation .... somewhere
..... though I can't find it .)

Cheers,
Rob
 
P

Paul Lalli

Sisyphus said:
You get the same for 2 ** 33 (and larger powers). Is this reliable, defined
behaviour ? Or is it machine dependent ? Or is it just plain undefined
behaviour ? I'm a little curious as to where the documentation is.

perldoc perlnumber
Yes - but shouldn't this be spelled out clearly in the perl docs ? (I would
think it *is* spelled out clearly in the perl documentation .... somewhere
.... though I can't find it .)

In perldoc perlnumber, it lists the six possible conversions (involving
to and from decimal strings, native integers, and native floats). I
believe the second rule listed applies:

"If the source number is outside of the limits representable in the
target form, a representation of the closest limit is used. (Loss of
information)"

The source number in this case (2 ** 33) is outside the limits
representable in the target form (native integer, as we specifically
requested an integer format in the sprintf9)), and so the
representation of the closest limit (2 ** 32 - 1) is used.

Paul Lalli
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
Eric J. Roode
Why would the buffer overflow? I thought if you did arithmetic that was
too big to fit into an integer, perl automagically promoted the number to a
floating-point.

perldoc perlnumber

(the situation is exactly the opposite than what you suggest; the
"default mode of operation" should be thought of as floating-point,
with demoting to integer when needed - e.g., for bitwise operations).
 
S

Sisyphus

..
..
In perldoc perlnumber, it lists the six possible conversions (involving
to and from decimal strings, native integers, and native floats). I
believe the second rule listed applies:

"If the source number is outside of the limits representable in the
target form, a representation of the closest limit is used. (Loss of
information)"

The source number in this case (2 ** 33) is outside the limits
representable in the target form (native integer, as we specifically
requested an integer format in the sprintf9)), and so the
representation of the closest limit (2 ** 32 - 1) is used.

That explains why 'printf("%b", 2 ** 32)' produces the output it does ...
but it's still not glaringly obvious (to me) that 2 & (2**32) is going to
produce '2'.

I also found in 'perldoc perlnumber':

Bitwise operators
Arguments are forced into the integer format if not strings.

I guess that if one understands that "integer format" means an integer in
the range -2**31..2**32-1(on 32-bit machines) and if one bears in mind the
"second rule" quoted above by Paul, then one would deduce that 2 & (2**32)
is going to be '2' .... if one is clever enough to make deductions :)

I thought this was documented more transparently somewhere ... but perhaps
it isn't.

Anyway, I don't really want to carry on about it as it's not such a *huge*
deal. Thanks Paul, for reminding me that 'perldoc perlnumber' has useful
information - especially concerning numbers :)

Cheers,
Rob
 
B

Big and Blue

Sisyphus said:
You get the same for 2 ** 33 (and larger powers). Is this reliable, defined
behaviour ?

Yes. Others have given the references.
Or is it machine dependent ?

I depends on the way perl was built, rather than the machine. eg: you
can happily run a Perl compiled for i586 (32-bit ints) on a 64-bit AMD64
Linux system, and it will produce a string of 1's. On the same system the
"native" pewrl (64-bit ints) produces 100000000000000000000000000000000.

So it depends on the target machine of the build rather than the
machine which happens to be running it.

That explains why 'printf("%b", 2 ** 32)' produces the output it does ...
but it's still not glaringly obvious (to me) that 2 & (2**32) is going to
produce '2'.

Why not? It's been shown that 2**32 is a string of 32 1's. If you AND
this with 10, why do you expect anything other than 10 as a result?
 
E

Eric J. Roode

Why not? It's been shown that 2**32 is a string of 32 1's.

It has?

--
Eric
`$=`;$_=\%!;($_)=/(.)/;$==++$|;($.,$/,$,,$\,$",$;,$^,$#,$~,$*,$:,@%)=(
$!=~/(.)(.).(.)(.)(.)(.)..(.)(.)(.)..(.)......(.)/,$"),$=++;$.++;$.++;
$_++;$_++;($_,$\,$,)=($~.$"."$;$/$%[$?]$_$\$,$:$%[$?]",$"&$~,$#,);$,++
;$,++;$^|=$";`$_$\$,$/$:$;$~$*$%[$?]$.$~$*${#}$%[$?]$;$\$"$^$~$*.>&$=`
 
B

Bill Ricker N1VUX

"Eric J. Roode" replied to:

Well, not mathematically.

But it has been shown that that is what happens, rather too often for
mathematical comfort.

Prior poster said -- not quoted by Eric --
] > Yes. Others have given the references.

the references are
perldoc perlop
perldoc perlnumber

In that large portion of the universe using Perl in the typically default
32-bit configuration, yes. In BIGINTs or 64-bit-Int Perl, no.

In machine language, requesting 2**32 in an INT32 gets you -1 (32 1's) (unless
you have a machine other than two's complement).

You could use the pragma "use bignum;" to make all your numbers mathematically
correct on any platform, but that is invasively contagiously expensive like $'
....
see YAPAC 2005 http://web.mit.edu/belg4mit/www/8/

When coerced to an integer, the Floatingpoint value 2 ** ( $INTSIZE + 1 )
wraps around to -1 (instead of raising an error as Ada programmers might
expect, or whatever else one might conjecture). It may be a float and (almost
or exactly) correct until then, but when coerced, it's gone. And Bit
operations pretty much force integer coercion. (If you want to bit-bang on
the floating point representation, you'll need to pack/unpack or other
marshalling hacks. But that's better done with Inline::C or Inline::Fortran
anyway.)

If you've built Perl with 64-bit ints on your platform, 2**32 is a string of
one 1 and 32 0's as it ought to be, but they won't fit in a 32-bit int. (If
you some how built Perl on a 36 bit machine, it would probably work there too,
but there aren't many DEC10's or MULTICs or Lisp Machines left.)

(If you need 64-bit Perl on 32-bit MS Windows, you can try Cygwin's
Gnu-for-Windows kit. It won't run as fast as on 64-bit hardware, but hey, at
least it's not BIGNUM slow. If your 686 is fast enough, it may be faster than
my slow old Alpha with 64bit Perl native.)

Bill
 
D

Dr.Ruud

Bill Ricker N1VUX:
See <
<quote>
"If the source number is outside of the limits representable in the
target form, a representation of the closest limit is used. (Loss of
information)"

The source number in this case (2 ** 33) is outside the limits
[...] so the
representation of the closest limit (2 ** 32 - 1) is used.
</>
 

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
474,176
Messages
2,570,950
Members
47,503
Latest member
supremedee

Latest Threads

Top