如何比较两个64位数字

时间:2011-03-28 17:21:28

标签: php

在PHP中,我有一个64位数字,代表必须完成的任务。第二个64位数表示已完成的任务:

$pack_code = 1001111100100000000000000011111101001111100100000000000000011111
$veri_code = 0000000000000000000000000001110000000000000000000000000000111110

我需要比较两者并提供完成任务的百分比数字。我可以遍历两者并查找设置了多少位,但我不知道这是否是最快的方式?

5 个答案:

答案 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 extensiongmp_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 Ba​​ker发布的代码来获得差异。

答案 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,......