在PHP中,我有一个64位数字,代表必须完成的任务。第二个64位数表示已完成的任务:
$pack_code = 1001111100100000000000000011111101001111100100000000000000011111
$veri_code = 0000000000000000000000000001110000000000000000000000000000111110
我需要比较两者并提供完成任务的百分比数字。我可以遍历两者并查找设置了多少位,但我不知道这是否是最快的方式?
答案 0 :(得分:2)
假设这些实际上是字符串,可能类似于:
$pack_code = '1001111100100000000000000011111101001111100100000000000000011111';
$veri_code = '0000000000000000000000000001110000000000000000000000000000111110';
$matches = array_intersect_assoc(str_split($pack_code),str_split($veri_code));
$finished_matches = array_intersect($matches,array(1));
$percentage = (count($finished_matches) / 64) * 100
答案 1 :(得分:2)
因为您将数字设为十六进制字符串而不是零和零,所以您需要做一些额外的工作。
PHP不能可靠地支持32位以上的数字作为整数。 64位支持需要在64位计算机上编译和运行。这意味着根据您的环境,尝试表示64位整数可能会失败。因此,确保PHP仅将这些数字作为字符串处理是很重要的。这并不难,因为来自数据库的十六进制字符串将是字符串,而不是整数。
这里有一些选择。第一个是using the GMP extension的gmp_xor
函数,它对两个数字执行按位XOR运算。当两个数字在该位置具有相反的位时,得到的数字将打开位,而当两个数字在该位置具有相同的位时关闭。然后,只需计算位数即可获得剩余的任务数。
另一种选择是将数字作为字符串转换为1和0的字符串,正如您在问题中所表达的那样。如果您有GMP,则可以使用gmp_init
将其作为base-16号码读取,并使用gmp_strval
将其作为base-2号码返回。
如果您不拥有GMP,this function provided in another answer(滚动到“第2步”)可以准确地将字符串数字转换为基数为2到36之间的任何数字。将比使用GMP慢。
在这两种情况下,你最终会得到一串1和0,并且可以使用像@Mark Baker发布的代码来获得差异。
答案 2 :(得分:1)
这种情况下的优化不值得考虑。我百分百肯定你不关心你的脚本是否会产生0.00000014秒。更快,我是对的? 只需循环遍历该数字的每一位,将其与另一位进行比较即可完成。
记住Donald Knuth的话:
我们应该忘记小的效率,大约97%的时间说:过早的优化是所有邪恶的根源。
答案 3 :(得分:1)
这段代码使用了PHP支持的GNU Multi Precision库,因为它是用C实现的,所以应该足够快,并且支持任意精度。
$pack_code = gmp_init("1001111100100000000000000011111101001111100100000000000000011111", 2);
$veri_code = gmp_init("0000000000000000000000000001110000000000000000000000000000111110", 2);
$number_of_different_bits = gmp_popcount(gmp_xor($pack_code, $veri_code));
答案 4 :(得分:0)
$a = 11111;
echo sprintf('%032b',$a)."\n";
$b = 12345;
echo sprintf('%032b',$b)."\n";
$c = $a & $b;
echo sprintf('%032b',$c)."\n";
$n=0;
while($c)
{
$n += $c & 1;
$c = $c >> 1;
}
echo $n."\n";
输出:
00000000000000000010101101100111
00000000000000000011000000111001
00000000000000000010000000100001
3
鉴于您的PHP-setuo可以处理64位,这可以很容易地扩展。
如果不是,您可以使用GNU Multiple Precision
来回避此限制您还可以拆分HEx-Representation,然后对这些相应的零件进行操作。因为你只需要1或0的本地事实,而不是实际代表的是哪个数字!我认为这样可以最好地解决您的问题。
例如:
0xF1A35C和0xD546C1
你只需要比较F和D的二进制版本,1和5,A和4,......