Re: Unintuitive expression evaluation
- From: "Tassilo v. Parseval" <tassilo.von.parseval@xxxxxxxxxxxxxx>
- Date: Fri, 28 Oct 2005 08:01:14 +0200
Also sprach A. Sinan Unur:
> Bill Davidsen <davidsen@xxxxxxxxxxxxxxxxxxxxx> wrote in
> news:mNa8f.3023$Y61.1523@xxxxxxxxxxxxxxxxxxxxxxxxxx:
>
>> I am reading a log file which has 32 bit unsigned values, and need to
>> take the difference between them. If the difference is negative I
>> assume that the data counter has rolled over, and I want to add 231 to
>> get the correct value. For readability I wanted to put the value in a
>> variable so it would be obvious what was happening.
>>
>> So I wrote:
>> $Roll32 = (1 << 32); # the way I would for a C macro
>> but the value was (after I did some looking) one! Then I wrote:
>> $Roll32 = 1 << 32; # in case the parens were a issue
>> bit it was still one, so I wrote:
>> $Roll32 = ( 4 * (1 << 30) ); # which works (4G)
>>
>> This is the first time perl has failed to do int=>double conversion
>> when expected (by me).
>
> The only thing that failed in this case is you.
>
>> Just a note in case someone else is ever doing
>> similar, perl on Linux 32 bit, v5.6.1, v5.8.0, v5.8.5 builds.
>
> You mean "just in case someone else refuses to read the documentation"?
>
> perldoc perlop:
>
> Shift Operators
> ...
> Either way, the implementation isn't going to generate results larger
> than the size of the integer type Perl was built with (32 bits or 64
> bits).
>
> The result of overflowing the range of the integers is undefined
> because it is undefined also in C. In other words, using 32-bit
> integers, "1 << 32" is undefined. Shifting by a negative number
> of bits is also undefined.
>
> How hard is it to read this, and understand it?
Considering that
$Roll32 = ( 4 * (1 << 30) );
gives the expected result, these paragraphs may be a tad difficult to
understand, particularly for people with a C-background.
Replacing a two-bit shift with a multiplication by four works because
perl internally upgrades (as needed) the scalar from holding a plain
integer to holding a double when doing the multiplication.
I think the left-shift operator could be made smarter so that it always
works up to 2**64 - 1, even on 32bit machines.
Tassilo
--
use bigint;
$n=71423350343770280161397026330337371139054411854220053437565440;
$m=-8,;;$_=$n&(0xff)<<$m,,$_>>=$m,,print+chr,,while(($m+=8)<=200);
.
- Follow-Ups:
- Re: Unintuitive expression evaluation
- From: Anno Siegel
- Re: Unintuitive expression evaluation
- References:
- Unintuitive expression evaluation
- From: Bill Davidsen
- Re: Unintuitive expression evaluation
- From: A. Sinan Unur
- Unintuitive expression evaluation
- Prev by Date: Re: Hash of hashes, of hashes, of arrays of hashes
- Next by Date: Re: to parse a string
- Previous by thread: Re: Unintuitive expression evaluation
- Next by thread: Re: Unintuitive expression evaluation
- Index(es):