473,320 Members | 1,856 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

& behaves differently

Hi,

why does the php expression

$result = 5543039447 & 2147483648;

when executed evaluate to 0, whereas the perl expression

$same = 5543039447 & 2147483648 ;

evaluate to 2147483648 ???

Fritz

Mar 3 '06 #1
30 1870
d
<fr*********@web.de> wrote in message
news:11*********************@i40g2000cwc.googlegro ups.com...
Hi,

why does the php expression

$result = 5543039447 & 2147483648;

when executed evaluate to 0, whereas the perl expression

$same = 5543039447 & 2147483648 ;

evaluate to 2147483648 ???
Because perl is screwed?

5543039447 = 101001010011001000001000111010111

and

2147483648 = 010000000000000000000000000000000

As you can see, if you and both of those, you get zero. It seems PHP is
right on this one.
Fritz


dave
Mar 3 '06 #2
Are you serious about this? I mean you are right that it should be
zero, but could it be, that I have to use a different expression? Or
use a function instead of using the & ? Have you tried it yourself on
your machine? Do you get the same result?

Mar 3 '06 #3
fr*********@web.de wrote:
Hi,

why does the php expression

$result = 5543039447 & 2147483648;

when executed evaluate to 0, whereas the perl expression

$same = 5543039447 & 2147483648 ;

evaluate to 2147483648 ???

Fritz


Because Perl is using 64 bit integers and PHP is using 32 bit integers.

2147483648 is not a valid value in 32 bit arithmetic. The largest value
you can have is 2147483647.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
Mar 3 '06 #4
d
<fr*********@web.de> wrote in message
news:11**********************@t39g2000cwt.googlegr oups.com...
Are you serious about this? I mean you are right that it should be
zero, but could it be, that I have to use a different expression? Or
use a function instead of using the & ? Have you tried it yourself on
your machine? Do you get the same result?


Those numbers are straight from a test I did on my machine. If you look at
those numbers expressed in binary, you can see that a bitwise and will
return 0, as there is only one bit set to 1 in the second number, and the
corresponding bit in the first number is a 0, hence the result of the
bitwise and is 0.

If perl gives you a different number, then perl either wasn't doing a
bitwise and (though the perl docs say otherwise), or you were using
different numbers...

cheers!

dave
Mar 3 '06 #5
d
"Jerry Stuckle" <js*******@attglobal.net> wrote in message
news:P4********************@comcast.com...
fr*********@web.de wrote:
Hi,

why does the php expression

$result = 5543039447 & 2147483648;

when executed evaluate to 0, whereas the perl expression

$same = 5543039447 & 2147483648 ;

evaluate to 2147483648 ???

Fritz

Because Perl is using 64 bit integers and PHP is using 32 bit integers.

2147483648 is not a valid value in 32 bit arithmetic. The largest value
you can have is 2147483647.


PHP interprets ints over 32 bits as floats, so they are valid.

"If you specify a number beyond the bounds of the integer type, it will be
interpreted as a float instead. Also, if you perform an operation that
results in a number beyond the bounds of the integer type, a float will be
returned instead."
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================

Mar 3 '06 #6
I'm porting some code from php to pearl. Do you a workaournd? I mean
how could I get this working under perl?

Mar 3 '06 #7
d
<fr*********@web.de> wrote in message
news:11**********************@t39g2000cwt.googlegr oups.com...
I'm porting some code from php to pearl. Do you a workaournd? I mean
how could I get this working under perl?


perl performs a bitwise and with the & operator, the same as php. The two
numbers you gave will always return 0, so I don't know what the original
code was doing, but it doesn't look like it was performing a bitwise and...
Mar 3 '06 #8
d wrote:
"Jerry Stuckle" <js*******@attglobal.net> wrote in message
news:P4********************@comcast.com...
fr*********@web.de wrote:
Hi,

why does the php expression

$result = 5543039447 & 2147483648;

when executed evaluate to 0, whereas the perl expression

$same = 5543039447 & 2147483648 ;

evaluate to 2147483648 ???

Fritz


Because Perl is using 64 bit integers and PHP is using 32 bit integers.

2147483648 is not a valid value in 32 bit arithmetic. The largest value
you can have is 2147483647.

PHP interprets ints over 32 bits as floats, so they are valid.

"If you specify a number beyond the bounds of the integer type, it will be
interpreted as a float instead. Also, if you perform an operation that
results in a number beyond the bounds of the integer type, a float will be
returned instead."

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================



In most cases, yes. However, you cannot perform bit operations on a
float. It must be an integer type.

So the value is converted back to an integer, and since it's outside the
bounds of a 32 bit integer the result is to strip off the high order bits.

The result is zero.

Sometimes a little knowledge is worse than no knowledge at all.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
Mar 3 '06 #9
fr*********@web.de wrote:
I'm porting some code from php to pearl. Do you a workaournd? I mean
how could I get this working under perl?


Fritz,

If the Perl (not Pearl) code is performing 32 bit operations, you should
have no problems. If it's performing 64 bit operations, and it with
0x7fffffff (the high order bit is a sign bit).

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
Mar 3 '06 #10
d
"Jerry Stuckle" <js*******@attglobal.net> wrote in message
news:6v******************************@comcast.com. ..
d wrote:
"Jerry Stuckle" <js*******@attglobal.net> wrote in message
news:P4********************@comcast.com...
fr*********@web.de wrote:

Hi,

why does the php expression

$result = 5543039447 & 2147483648;

when executed evaluate to 0, whereas the perl expression

$same = 5543039447 & 2147483648 ;

evaluate to 2147483648 ???

Fritz
Because Perl is using 64 bit integers and PHP is using 32 bit integers.

2147483648 is not a valid value in 32 bit arithmetic. The largest value
you can have is 2147483647.

PHP interprets ints over 32 bits as floats, so they are valid.

"If you specify a number beyond the bounds of the integer type, it will
be interpreted as a float instead. Also, if you perform an operation that
results in a number beyond the bounds of the integer type, a float will
be returned instead."

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================



In most cases, yes. However, you cannot perform bit operations on a
float. It must be an integer type.

So the value is converted back to an integer, and since it's outside the
bounds of a 32 bit integer the result is to strip off the high order bits.

The result is zero.


The result is zero regardless of whether that bit is there or not :)
Sometimes a little knowledge is worse than no knowledge at all.

Indeed.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================

Mar 3 '06 #11
d wrote:
"Jerry Stuckle" <js*******@attglobal.net> wrote in message
news:6v******************************@comcast.com. ..
d wrote:
"Jerry Stuckle" <js*******@attglobal.net> wrote in message
news:P4********************@comcast.com...
fr*********@web.de wrote:
>Hi,
>
>why does the php expression
>
>$result = 5543039447 & 2147483648;
>
>when executed evaluate to 0, whereas the perl expression
>
>$same = 5543039447 & 2147483648 ;
>
>evaluate to 2147483648 ???
>
>Fritz
>

Because Perl is using 64 bit integers and PHP is using 32 bit integers.

2147483648 is not a valid value in 32 bit arithmetic. The largest value
you can have is 2147483647.
PHP interprets ints over 32 bits as floats, so they are valid.

"If you specify a number beyond the bounds of the integer type, it will
be interpreted as a float instead. Also, if you perform an operation that
results in a number beyond the bounds of the integer type, a float will
be returned instead."

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================

In most cases, yes. However, you cannot perform bit operations on a
float. It must be an integer type.

So the value is converted back to an integer, and since it's outside the
bounds of a 32 bit integer the result is to strip off the high order bits.

The result is zero.

The result is zero regardless of whether that bit is there or not :)

Sometimes a little knowledge is worse than no knowledge at all.

Indeed.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================



Actually, 0x80000000 is -2147483647 decimal. So the result is not zero.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
Mar 3 '06 #12

Jerry Stuckle wrote:
d wrote:
"Jerry Stuckle" <js*******@attglobal.net> wrote in message
news:6v******************************@comcast.com. ..
d wrote:

"Jerry Stuckle" <js*******@attglobal.net> wrote in message
news:P4********************@comcast.com...
>fr*********@web.de wrote:
>
>
>>Hi,
>>
>>why does the php expression
>>
>>$result = 5543039447 & 2147483648;
>>
>>when executed evaluate to 0, whereas the perl expression
>>
>>$same = 5543039447 & 2147483648 ;
>>
>>evaluate to 2147483648 ???
>>
>>Fritz
>>
>
>Because Perl is using 64 bit integers and PHP is using 32 bit integers.
>
>2147483648 is not a valid value in 32 bit arithmetic. The largest value
>you can have is 2147483647.
PHP interprets ints over 32 bits as floats, so they are valid.

"If you specify a number beyond the bounds of the integer type, it will
be interpreted as a float instead. Also, if you perform an operation that
results in a number beyond the bounds of the integer type, a float will
be returned instead."

>--
>==================
>Remove the "x" from my email address
>Jerry Stuckle
>JDS Computer Training Corp.
>js*******@attglobal.net
>==================

In most cases, yes. However, you cannot perform bit operations on a
float. It must be an integer type.

So the value is converted back to an integer, and since it's outside the
bounds of a 32 bit integer the result is to strip off the high order bits.

The result is zero.

The result is zero regardless of whether that bit is there or not :)

Sometimes a little knowledge is worse than no knowledge at all.

Indeed.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================



Actually, 0x80000000 is -2147483647 decimal. So the result is not zero.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================

How can I port the php code, which return 0 (zero), and looks exactly
like this:

<?php
$a = 5543039447;
$b = 2147483648;
$result = ($a & $b);
echo "$result\n" ;
?>

to perl? In perl almost the exactly same code:

#!/usr/bin/perl
$a = 5543039447;
$b = 2147483648;
$result = ($a & $b);
print "$result\n" ;

returns 2147483648.

How do I have to modify the perl code, so that it will actually do a
bitwise and? I don't get - any workaround? Somethings I'm not getting
here? I'm using linux debian/sarge with an intel 32 bit prozessor.

Fritz

Mar 4 '06 #13
fr*********@web.de wrote:
Jerry Stuckle wrote:
d wrote:
"Jerry Stuckle" <js*******@attglobal.net> wrote in message
news:6v******************************@comcast.c om...
d wrote:
>"Jerry Stuckle" <js*******@attglobal.net> wrote in message
>news:P4********************@comcast.com...
>
>
>
>>fr*********@web.de wrote:
>>
>>
>>
>>>Hi,
>>>
>>>why does the php expression
>>>
>>>$result = 5543039447 & 2147483648;
>>>
>>>when executed evaluate to 0, whereas the perl expression
>>>
>>>$same = 5543039447 & 2147483648 ;
>>>
>>>evaluate to 2147483648 ???
>>>
>>>Fritz
>>>
>>
>>Because Perl is using 64 bit integers and PHP is using 32 bit integers.
>>
>>2147483648 is not a valid value in 32 bit arithmetic. The largest value
>>you can have is 2147483647.
>
>
>PHP interprets ints over 32 bits as floats, so they are valid.
>
>"If you specify a number beyond the bounds of the integer type, it will
>be interpreted as a float instead. Also, if you perform an operation that
>results in a number beyond the bounds of the integer type, a float will
>be returned instead."
>
>
>
>
>>--
>>==================
>>Remove the "x" from my email address
>>Jerry Stuckle
>>JDS Computer Training Corp.
>>js*******@attglobal.net
>>==================
>
>
>
In most cases, yes. However, you cannot perform bit operations on a
float. It must be an integer type.

So the value is converted back to an integer, and since it's outside the
bounds of a 32 bit integer the result is to strip off the high order bits.

The result is zero.
The result is zero regardless of whether that bit is there or not :)

Sometimes a little knowledge is worse than no knowledge at all.

Indeed.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================

Actually, 0x80000000 is -2147483647 decimal. So the result is not zero.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================


How can I port the php code, which return 0 (zero), and looks exactly
like this:

<?php
$a = 5543039447;
$b = 2147483648;
$result = ($a & $b);
echo "$result\n" ;
?>

to perl? In perl almost the exactly same code:

#!/usr/bin/perl
$a = 5543039447;
$b = 2147483648;
$result = ($a & $b);
print "$result\n" ;

returns 2147483648.

How do I have to modify the perl code, so that it will actually do a
bitwise and? I don't get - any workaround? Somethings I'm not getting
here? I'm using linux debian/sarge with an intel 32 bit prozessor.

Fritz


I would suggest asking this in a Perl group. I'm a PHP programmer - I
know nothing about Perl.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
Mar 4 '06 #14
"fr*********@web.de" <fr*********@web.de> wrote:

<?php
$a = 5543039447;
$b = 2147483648;
$result = ($a & $b);
echo "$result\n" ;
?>

to perl? In perl almost the exactly same code:

#!/usr/bin/perl
$a = 5543039447;
$b = 2147483648;
$result = ($a & $b);
print "$result\n" ;

returns 2147483648.

How do I have to modify the perl code, so that it will actually do a
bitwise and? I don't get - any workaround? Somethings I'm not getting
here? I'm using linux debian/sarge with an intel 32 bit prozessor.


The basic problem here is that what you are asking for is nonsense. GIGO.

Both of your numbers are too large to fit into an unsigned 32-bit value.
When that happens, both languages will automatically convert to using
floating point to store those values. $a and $b are FLOATING POINT.

However, bitwise operations do not make sense for floating point values.
Thus, both languages must convert the floats back to 32-bit integers. But,
we already know that the values are too big for that. So, there is an
overflow. It just turns out that the two languages handle this overflow
differently.

PHP handles the overflow by throwing away the upper bits, leaving you with
only the bottom 32 bits of the converted value. Perl handles the overflow
by "pegging"; it returns 2^32-1, or 4,294,967,295. That value happens to
have all 32 bit set, so the bitwise "and" returns the second value.

If you need to handle integers larger than 32-bits in Perl, you can use the
Math::BigInt module to do that.
--
- Tim Roberts, ti**@probo.com
Providenza & Boekelheide, Inc.
Mar 5 '06 #15

Tim Roberts wrote:
"fr*********@web.de" <fr*********@web.de> wrote:

<?php
$a = 5543039447;
$b = 2147483648;
$result = ($a & $b);
echo "$result\n" ;
?>

to perl? In perl almost the exactly same code:

#!/usr/bin/perl
$a = 5543039447;
$b = 2147483648;
$result = ($a & $b);
print "$result\n" ;

returns 2147483648.

How do I have to modify the perl code, so that it will actually do a
bitwise and? I don't get - any workaround? Somethings I'm not getting
here? I'm using linux debian/sarge with an intel 32 bit prozessor.


The basic problem here is that what you are asking for is nonsense. GIGO.

Both of your numbers are too large to fit into an unsigned 32-bit value.
When that happens, both languages will automatically convert to using
floating point to store those values. $a and $b are FLOATING POINT.

However, bitwise operations do not make sense for floating point values.
Thus, both languages must convert the floats back to 32-bit integers. But,
we already know that the values are too big for that. So, there is an
overflow. It just turns out that the two languages handle this overflow
differently.

PHP handles the overflow by throwing away the upper bits, leaving you with
only the bottom 32 bits of the converted value. Perl handles the overflow
by "pegging"; it returns 2^32-1, or 4,294,967,295. That value happens to
have all 32 bit set, so the bitwise "and" returns the second value.

If you need to handle integers larger than 32-bits in Perl, you can use the
Math::BigInt module to do that.
--
- Tim Roberts, ti**@probo.com
Providenza & Boekelheide, Inc.


Thanks Tim! Any ideas how I could emulate the overflow, so that I get
the same overflow behaviour in perl, maybe by writting a function for
it?!

Mar 5 '06 #16
fr*********@web.de said the following on 05/03/2006 11:39:
Tim Roberts wrote:

PHP handles the overflow by throwing away the upper bits, leaving you with
only the bottom 32 bits of the converted value. Perl handles the overflow
by "pegging"; it returns 2^32-1, or 4,294,967,295. That value happens to
have all 32 bit set, so the bitwise "and" returns the second value.

If you need to handle integers larger than 32-bits in Perl, you can use the
Math::BigInt module to do that.


Thanks Tim! Any ideas how I could emulate the overflow, so that I get
the same overflow behaviour in perl, maybe by writting a function for
it?!

Why would you want to do this? Either way, you're not going to get the
"correct" answer (in terms of mathematically correct).

Your best bet would be to go with the module that Tim suggested (or the
equivalent (?) in PHP - BCMath). Alternatively, re-think your algorithm
so that it doesn't require >32-bit numbers. After all, where are these
numbers going to come from?

--
Oli
Mar 5 '06 #17

Oli Filth wrote:
fr*********@web.de said the following on 05/03/2006 11:39:
Tim Roberts wrote:

PHP handles the overflow by throwing away the upper bits, leaving you with
only the bottom 32 bits of the converted value. Perl handles the overflow
by "pegging"; it returns 2^32-1, or 4,294,967,295. That value happens to
have all 32 bit set, so the bitwise "and" returns the second value.

If you need to handle integers larger than 32-bits in Perl, you can use the
Math::BigInt module to do that.


Thanks Tim! Any ideas how I could emulate the overflow, so that I get
the same overflow behaviour in perl, maybe by writting a function for
it?!

Why would you want to do this? Either way, you're not going to get the
"correct" answer (in terms of mathematically correct).

Your best bet would be to go with the module that Tim suggested (or the
equivalent (?) in PHP - BCMath). Alternatively, re-think your algorithm
so that it doesn't require >32-bit numbers. After all, where are these
numbers going to come from?

--
Oli


Hi,

because I have to port the the following function including the
overflow behaviour from php to perl:

//unsigned shift right
function fillWithZeroes($a, $b)
{
$z = hexdec(80000000);
if ($z & $a)
{
$a = ($a>>1);
$a &= (~$z);
$a |= 0x40000000;
$a = ($a>>($b-1));
}
else
{
$a = ($a>>$b);
}
return $a;
}

Mar 5 '06 #18
fr*********@web.de said the following on 05/03/2006 12:33:
Oli Filth wrote:
fr*********@web.de said the following on 05/03/2006 11:39:
Tim Roberts wrote:
PHP handles the overflow by throwing away the upper bits, leaving you with
only the bottom 32 bits of the converted value. Perl handles the overflow
by "pegging"; it returns 2^32-1, or 4,294,967,295. That value happens to
have all 32 bit set, so the bitwise "and" returns the second value.

If you need to handle integers larger than 32-bits in Perl, you can use the
Math::BigInt module to do that.
Thanks Tim! Any ideas how I could emulate the overflow, so that I get
the same overflow behaviour in perl, maybe by writting a function for
it?!


Why would you want to do this? Either way, you're not going to get the
"correct" answer (in terms of mathematically correct).


because I have to port the the following function including the
overflow behaviour from php to perl:

//unsigned shift right
function fillWithZeroes($a, $b)
{
$z = hexdec(80000000);
if ($z & $a)
{
$a = ($a>>1);
$a &= (~$z);
$a |= 0x40000000;
$a = ($a>>($b-1));
}
else
{
$a = ($a>>$b);
}
return $a;
}


Why would you be concerned about behaviour in out-of-range input
conditions, as they're technically meaningless, and wouldn't be
relied-upon except in the most bizarre situations? What's more, if you
did make your Perl function consistent with PHP behaviour, it would then
be inconsistent with the rest of Perl's behaviour.

Anyway, I don't think the PHP behaviour Tim describes is consistent.
For instance, try this in PHP:

$a = 5543039444;
$b = $a * 10000000000;

echo $a . " => " . intval($a) . "\n";
echo $b . " => " . intval($b) . "\n";

PHP is clearly not just converting the floats to fully-represented
integers and retaining only the 32 LSBs.

--
Oli
Mar 5 '06 #19

Oli Filth wrote:
fr*********@web.de said the following on 05/03/2006 12:33:
Oli Filth wrote:
fr*********@web.de said the following on 05/03/2006 11:39:
Tim Roberts wrote:
> PHP handles the overflow by throwing away the upper bits, leaving you with
> only the bottom 32 bits of the converted value. Perl handles the overflow
> by "pegging"; it returns 2^32-1, or 4,294,967,295. That value happens to
> have all 32 bit set, so the bitwise "and" returns the second value.
>
> If you need to handle integers larger than 32-bits in Perl, you can use the
> Math::BigInt module to do that.
Thanks Tim! Any ideas how I could emulate the overflow, so that I get
the same overflow behaviour in perl, maybe by writting a function for
it?!

Why would you want to do this? Either way, you're not going to get the
"correct" answer (in terms of mathematically correct).


because I have to port the the following function including the
overflow behaviour from php to perl:

//unsigned shift right
function fillWithZeroes($a, $b)
{
$z = hexdec(80000000);
if ($z & $a)
{
$a = ($a>>1);
$a &= (~$z);
$a |= 0x40000000;
$a = ($a>>($b-1));
}
else
{
$a = ($a>>$b);
}
return $a;
}


Why would you be concerned about behaviour in out-of-range input
conditions, as they're technically meaningless, and wouldn't be
relied-upon except in the most bizarre situations? What's more, if you
did make your Perl function consistent with PHP behaviour, it would then
be inconsistent with the rest of Perl's behaviour.

Anyway, I don't think the PHP behaviour Tim describes is consistent.
For instance, try this in PHP:

$a = 5543039444;
$b = $a * 10000000000;

echo $a . " => " . intval($a) . "\n";
echo $b . " => " . intval($b) . "\n";

PHP is clearly not just converting the floats to fully-represented
integers and retaining only the 32 LSBs.

--
Oli


Well, I guess the program I'm porting relies on this strange behaviour.
That's for sure. I did not write it. I'm just trying to port it. Could
it be that php ocde above will convert those numbers to unsigned ints
so that no overflow takes place?!

Mar 5 '06 #20
<fr*********@web.de> wrote in message
news:11*********************@v46g2000cwv.googlegro ups.com...
I have to port the the following function including the
overflow behaviour from php to perl:

//unsigned shift right
function fillWithZeroes($a, $b)
{
$z = hexdec(80000000);
if ($z & $a)
{
$a = ($a>>1);
$a &= (~$z);
$a |= 0x40000000;
$a = ($a>>($b-1));
}
else
{
$a = ($a>>$b);
}
return $a;
}


Now that you've actually posted your code, it's possible to (finally)
understand something about the problem you're having.

First, I have to point out that whoever wrote this code did so under the
assumption that $a would be a 32-bit integer and $b would be in the range 0
to 31. The constant 80000000 is equivalent to the comment "This function
assumes $a is a 32-bit integer" (but see my note below). And if that's the
case, then $b is in the range 0 to 31 (otherwise the behaviour is
undefined).

Moreover, the author assumes that on the machine executing this code ">>"
might do sign bit propogation, but might not, and it might do sign bit
extension, or might not. Again, this is clear from the structure of the
code ("$a |= 0x40000000" deals with sign bit propogation, "$a &= (~$z)"
deals with sign bit extension).

But there are still puzzles in this code. The expression "hexdec(80000000)"
yields a floating point value in PHP (in modern PHP's--in older ones it's
undefined). As others have already pointed out, floating point has no
business being used in a function like this! This function was not written
to use floating point. The person who wrote it clearly assumed it was going
to handle 32-bit integers.

The entire function would make PERFECT sense if the opening line were "$z =
0x80000000"...is there any possibility that somebody changed it?

I cannot see where "overflow" comes into this function at all. Nothing in
it overflows.

Of course, PHP being PHP, you can pass whatever you want for $a and $b and
the function will doubtless deliver some result, probably without issuing
any error message. This is one of the nice things, and one of the not nice
things, about PHP. But if your goal is to reproduce that out-of-bounds
behaviour on some other machine, good luck. Actually, bad luck, because it
won't happen.

I don't know how PHP actually executes right shift (>>). But if it uses the
underlying hardware, which it might well do, be aware that when you
"overshift" (shift by the word width or more, so 32 or more, in this case),
most Intel chips do the shift modulo the word width, and most Motorola chips
use the value you supplied. So the expression $a >> 32 will typically give
you $a on an Intel chip, and 0 on a Motorola chip. Which is why you see
people warning you (and pay attention to their warning) that shifting by the
word width or more is UNDEFINED. Attempting to port such code is going to
bring you nothing but grief.

You need to take a deep breath, step back from this function, and examine
the code that calls it. Someplace the original author's assumptions are
being violated.

-Dana


Mar 5 '06 #21
Thanks Dana and thanks to rest of the people who responded.

I have debug both scripts an figured out that the program breaks, when
it's processing the values

a=5496229061, b=13

The php script returns 146638 and the perl script 524287. So also the
operation $a = ($a >> $b) yields different values in php and perl.

Or could it be, that php is smart enough to create a unsigned integer,
wheras perl does not and therefore an overflow occurs? Anyway here you
have the possibiliy of an overflow depending on how $a is handled.

Do you think >> differs in perl and php or is it an overflow problem?

Mar 5 '06 #22
My e-mail address doesn't have a 2 in it.
<fr*********@web.de> wrote in message
news:11*********************@i39g2000cwa.googlegro ups.com...
Thanks Dana and thanks to rest of the people who responded.

I have debug both scripts an figured out that the program breaks, when
it's processing the values

a=5496229061, b=13

The php script returns 146638 and the perl script 524287. So also the
operation $a = ($a >> $b) yields different values in php and perl.

Or could it be, that php is smart enough to create a unsigned integer,
wheras perl does not and therefore an overflow occurs? Anyway here you
have the possibiliy of an overflow depending on how $a is handled.

Do you think >> differs in perl and php or is it an overflow problem?


Please remember that this function is ONLY VALID when fed a $a that fits
within a 32-bit signed integer. As has been pointed out, 5,496,229,061
doesn't fit within a 32-bit signed int (limit is 2,147,483,647). Nor does
it fit within an unsigned 32-bit int (limit is 4,294,967,295). It isn't a
question of whether PHP is using signed or unsigned arithmetic. It is
surely being stored as a float of some sort (which will vary from one
computer to another).

Therefore, you simply cannot pass it to this function and expect predictable
results. Your results will depend upon the nitty-gritty details of the
language, the computer you're on, the version of the software you're
using...in short, you cannot pass this function 5496229061 and ask
meaningful questions about the results. It's not an overflow problem. It
does not depend on how >> works. It has to do with how numbers are
represented in memory.

If you have software that is feeding 5496229061 to this function, then you
have a HUGE problem. Evidently the software depends upon the specific value
that this function HAPPENS TO RETURN when run on a CERTAIN HARDWARE PLATFORM
on a PARTICULAR VERSION OF PHP. Aside from the issue of porting it to perl,
I am certain that this software will break (in unpredictable ways) simply by
the passage of time, because if you try to run it on a different computer,
it will likely break. If you upgrade PHP, it will likely break. And so on
and so forth. This is a time bomb that will sooner or later detonate.

You cannot easily fix this problem by messing around with this function.
Your software is breaking the rules, and you are suffering the consequences.

You could study the floating point representation of 5,496,229,061 and see
if the results you are getting can be predicted from that (this should be
possible, since computers are not whimsical). You would need to look at the
PHP code that implements >> and see what it does with a floating point (this
is where open source is *really* handy). And you could try to force perl to
do its arithmetic the same way. And you could meticulously document the
resulting code. It should be possible to do. It's what I would do if this
were my problem to solve and I wasn't able to fix the real problem, which is
that some idiot wrote code that is passing bogus values to this function.

-Dana
Mar 5 '06 #23
Hi Dana,

the complete code of the php, which I`m supposed to port to perl can be
found at http://www.googlecommunity.com/scrip...e-pagerank.php

It actually computes the pagerank of a website. Most of the script is
calculating a checksum, which is needed to calculate the pagerank.

It's really strange the code, but my job is just to port it, but it's
not so easy as you can see?

Mar 5 '06 #24
fr*********@web.de said the following on 05/03/2006 21:06:
Hi Dana,

the complete code of the php, which I`m supposed to port to perl can be
found at http://www.googlecommunity.com/scrip...e-pagerank.php

It actually computes the pagerank of a website. Most of the script is
calculating a checksum, which is needed to calculate the pagerank.

It's really strange the code, but my job is just to port it, but it's
not so easy as you can see?


Basically, PHP doesn't do unsigned arithmetic. This algorithm probably
originated in C or something similar, where you can specify unsigned
data types and everything will work fine. The implementation this guy
created relies on the current conversions occurring in PHP; on a 64-bit
platform this would probably fail.

However:

http://tumanov.com/entry/209
It's talking about VBScript, but the problem he describes is identical.

--
Oli
Mar 5 '06 #25
> //unsigned shift right
function fillWithZeroes($a, $b)
{
$z = hexdec(80000000);
if ($z & $a)
{
$a = ($a>>1);
$a &= (~$z);
$a |= 0x40000000;
$a = ($a>>($b-1));
}
else
{
$a = ($a>>$b);
}
return $a;
}


This should handle an arbitrary number of bits for $a, allowing $b to be
greater than the number of machine word bits.

// Assuming 32-bit (1 sign) integer length.
function fillWithZeroes($a, $b)
{
// In PHP you could use is_float($a), but I don't know
// the equivalent Perl function.
if ($a > 0x7FFFFFFF)
{
// It is some FP number, must emulate shift with division.
$d = exp(2, $b);
$a = round($a / $d);
// Return int if possible.
if ($a <= 0x7FFFFFFF)
$a = (int)$a;
}
else
$a >>= $b;
return $a;
}

This yelds correct results as long as FP numbers have enugh precision. This
is obviously NOT a safe assumption; yet if FP numbers have 53 + 1
significand bits (64-bits IEEE FP), this fillWithZeroes should be able to
handle numbers from 0 to 2^54 - 1.

--
ColdShine

"Experience is a hard teacher: she gives the test first, the lesson
afterwards." - Vernon Sanders law
Mar 5 '06 #26

ColdShine wrote:
//unsigned shift right
function fillWithZeroes($a, $b)
{
$z = hexdec(80000000);
if ($z & $a)
{
$a = ($a>>1);
$a &= (~$z);
$a |= 0x40000000;
$a = ($a>>($b-1));
}
else
{
$a = ($a>>$b);
}
return $a;
}


This should handle an arbitrary number of bits for $a, allowing $b to be
greater than the number of machine word bits.

// Assuming 32-bit (1 sign) integer length.
function fillWithZeroes($a, $b)
{
// In PHP you could use is_float($a), but I don't know
// the equivalent Perl function.
if ($a > 0x7FFFFFFF)
{
// It is some FP number, must emulate shift with division.
$d = exp(2, $b);
$a = round($a / $d);
// Return int if possible.
if ($a <= 0x7FFFFFFF)
$a = (int)$a;
}
else
$a >>= $b;
return $a;
}

This yelds correct results as long as FP numbers have enugh precision. This
is obviously NOT a safe assumption; yet if FP numbers have 53 + 1
significand bits (64-bits IEEE FP), this fillWithZeroes should be able to
handle numbers from 0 to 2^54 - 1.

--
ColdShine

"Experience is a hard teacher: she gives the test first, the lesson
afterwards." - Vernon Sanders law


Hi Coldhine, thanks for the workaround. I had to slightly change the
code, since perl does not have a rounding function and have now:

sub zeroFill2()
{
my ($a, $b) = @_;
# In PHP you could use is_float($a), but I don't know
# the equivalent Perl function.
if ($a > 0x7FFFFFFF)
{
# It is some FP number, must emulate shift with division.
$d = 2 ** $b;
$a = round($a / $d);

# Return int if possible.
if ($a <= 0x7FFFFFFF)
{
return int($a);
}
}
else
{
$a = ($a >> $b);
}
return $a;

}

sub round()
{
my ($number) = @_;
return int($number + .5 * ($number <=> 0));
}

Problem still remains so. This function returns 679118 instead of the
needed 154830. What should I change, so that it will return the right
numbers?

Mar 6 '06 #27
Oli Filth <ca***@olifilth.co.uk> wrote:

Anyway, I don't think the PHP behaviour Tim describes is consistent.
For instance, try this in PHP:

$a = 5543039444;
$b = $a * 10000000000;

echo $a . " => " . intval($a) . "\n";
echo $b . " => " . intval($b) . "\n";

PHP is clearly not just converting the floats to fully-represented
integers and retaining only the 32 LSBs.


Actually, you're seeing an artifact of the design of the x86 FPU here. With
any fewer zeros, your code will print a number.

I looked up the PHP code; it is doing a simple C cast to unsigned long, and
writing the equivalent C program gets the same result:

int main(void)
{
double a = 5543039444;
double b = a * 10000000000;
printf( "%f %d\n", b, (unsigned long)b);
return 0;
}

C:\tmp>x
55430394439999996000.000000 0

C:\tmp>

The reason is that the mantissa in your example requires more than 64 bits,
which means it can no longer be represented exactly in an 80-bit FPU
register. In that case, the "fist" instruction raises an exception and
returns the "most negative integer". For an unsigned long, that is 0.
--
- Tim Roberts, ti**@probo.com
Providenza & Boekelheide, Inc.
Mar 7 '06 #28
In article <11**********************@t39g2000cwt.googlegroups .com>,
"fr*********@web.de" <fr*********@web.de> wrote:
Are you serious about this? I mean you are right that it should be
zero, but could it be, that I have to use a different expression? Or
use a function instead of using the & ? Have you tried it yourself on
your machine? Do you get the same result?


If I were given such a porting job, I would be inclined to take a step
back and see what the purpose of the function was. As has been
eloquently pointed out, you are unlikely to succeed if all you do is try
to port the code in a mechanical way.

Is the function called in one place in the code? In many? Figure out
what you want the function to do and only then worry about how to do it.

-- tim
Mar 7 '06 #29
I found a perl version: http://www.everyscript.de/PRank.htm

Mar 15 '06 #30
I found a perl version: http://www.everyscript.de/PRank.htm

Can you convert that back to PHP for 64 bit machines?

Mar 15 '06 #31

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Scott Matthews | last post by:
I've recently come upon an odd Javascript (and/or browser) behavior, and after hunting around the Web I still can't seem to find an answer. Specifically, I have noticed that the Javascript...
6
by: ss | last post by:
Hi I built an exe in console debug mode & Release mode . The console debug mode -exe works fine ...but the release mode EXE starts well but fails mid way . The exe is being started as a...
3
by: Faith | last post by:
Hi all, I have a serious problem that I am not sure whether its a bug in the Microsoft Visual C++ or something that I am doing wrong. The problem is (as noted in the Subject) is that my program...
5
by: jab3 | last post by:
(again :)) Hello everyone. I'll ask this even at risk of being accused of not researching adequately. My question (before longer reasoning) is: How does declaring (or defining, whatever) a...
44
by: Agoston Bejo | last post by:
What happens exactly when I do the following: struct A { int i; string j; A() {} }; void f(A& a) { cout << a.i << endl;
15
by: Joe Weinstein | last post by:
Hi. Below is a simple JDBC program to insert and extract a numerical value. When ResultSet.getDouble() is called, the same program produces different output on solaris than it does on Linux. I...
17
by: Steve-O | last post by:
The following code works great in FireFox, Opera, Netscape, Safari, and Gecko, but NOT IE. Why? I tried using 'native' js with setInterval and setTimeout, but I get the same result. My IE...
9
by: rn5a | last post by:
Is putting a VB class file in the special directory named App_Code the same as relocating the VB class file from the App_Code directory to another directory & then using the VBC tool, compiling the...
10
by: Andrew Wan | last post by:
I have been having a nightmare with ASP/ASP.NET & IIS6. We use Msxml2.DOMDocument.4.0 object to create a XML object in ASP. The Msxml2.DOMDocument.4.0 is from the Windows Platform SDK Feb 2003...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.