我正在尝试编写一种算法,以通过截断将64Bit整数转换为32Bit,并返回一个准确表示32Bit值的值。明显的问题是PHP中的整数只有64Bit(不包括32Bit系统)。
我首先尝试了以下方法:
$x = $v & 0xFFFFFFFF
因此,如果$v = PHP_INT_MAX
,$x
是4294967295
,那么我真的很想-1
。我知道这样做的原因是,当用64位整数表示时,PHP将零添加到最后32位,这就是为什么我得到正数的原因。
到目前为止,我的解决方案是:
function convert64BitTo32Bit(int $v): int
{
$v &= 0xFFFFFFFF;
if ($v & 0x80000000) {
return $v | 0xFFFFFFFF00000000;
}
return $v;
}
我非常确定它是正确的。我的问题是,它需要if
语句来检查截断的数字是否为负。我真的希望有一个按位解决方案。可能不可能,但是我想问一下。
编辑:
可以将问题简化为解决方案的一部分。即,如果第一位为1
,则将所有位设为1
,如果第一位为0
,则将所有位设为0
。
# example assumes input is the LSBs of an 8Bit integer.
# scale for 64Bit and the same solution should work.
op(1010) = 1111
op(0101) = 0000
op(0000) = 0000
op(1000) = 1111
op(0001) = 0000
我将能够使用LSB导出此值,然后将其屏蔽到64位整数的MSB上。这就是我现在想要找出的,尽管我试图避免创建怪物方程。
答案 0 :(得分:2)
使用按位运算可能是一种更优雅/有效的方法,但是您也可以使用CREATE VIEW customer_master as
(
select *
from survey_info
full join survey_responses on survey_info.submissionid =survey_responses.submissionid
);
和 +-------+
----+ | | +----
| | | |
----+ | | +----
+-------+
强制进行转换。例如:打包为未签名,打包为已签名。
pack()
我很好奇您将其应用于什么,因为几年前当我将应用程序从32位计算机迁移到64位计算机时,我不得不用同样的方法破坏哈希函数,但是我可以不记得那是什么。
编辑:出于某种原因,我记得Two's Complement很辛苦。从字面上看,只需反转并添加一个即可。
unpack()
编辑2:我看到您想将其扩展为任意位长度,在这种情况下,您只需要计算掩码而不是显式设置它们即可:
function overflow32($in) {
return unpack('l', pack('i', $in & 0xFFFFFFFF))[1];
}
var_dump( overflow32(pow(2,33)-1) ); // int(-1)
我留在调试function overflow32($in) {
if( $in & 0x80000000 ) {
return ( ( ~$in & 0xFFFFFFFF) + 1 ) * -1;
} else {
return $in & 0xFFFFFFFF;
}
}
var_dump( kludge32(pow(2,33)-1) );
中以获取输出味道:
function overflow_bits($in, $bits=32) {
$sign_mask = 1 << $bits-1;
$clamp_mask = ($sign_mask << 1) - 1;
var_dump(
decbin($in),
decbin($sign_mask),
decbin($clamp_mask)
);
if( $in & $sign_mask ) {
return ( ( ~$in & $clamp_mask) + 1 ) * -1;
} else {
return $in & $clamp_mask;
}
}
var_dump(
overflow_bits(pow(2, 31), 32),
overflow_bits(pow(2, 15), 16),
overflow_bits(pow(2, 7), 8)
);
答案 1 :(得分:0)
我想我已经破解了:
function overflow32Bit(int $x): int
{
return ($x & 0xFFFFFFFF) | ((($x & 0xFFFFFFFF) >> 31) * ((2 ** 32) - 1) << 32);
}
var_dump(overflow32Bit(PHP_INT_MAX)); // -1 correct
var_dump(overflow32Bit(PHP_INT_MAX - 1)); // -2 correct
var_dump(overflow32Bit(PHP_INT_MIN)); // 0 correct
var_dump(overflow32Bit((2 ** 31) - 1)); // 2147483647 correct
var_dump(overflow32Bit((2 ** 31))); // -2147483647 correct
var_dump(overflow32Bit(0xFFFFFFFF)); // -1 correct
var_dump(overflow32Bit(0x7FFFFFFF)); // 2147483647 correct
解决方案实际上是盯着我。获取第一位的值,然后将其乘以无符号32位整数的最大值。
如果有人可以提出更好或更短的解决方案,我也会接受。
PS。这仅适用于32Bit,我也打算将此证明用于16Bit和8Bit。
展开,输入$x
,输出$z
。
$x = PHP_INT_MAX;
$y = (2 ** 32) - 1;
$z = ($x & $y) | ((($x & $y) >> 31) * ($y << 32));
var_dump($z);