开发者

How to compare two 64 bit numbers

开发者 https://www.devze.com 2023-02-20 13:18 出处:网络
In PHP I have a 64 bit number which represents tasks that must be completed.A second 64 bit number represents the tasks which have been completed:

In PHP I have a 64 bit number which represents tasks that must be completed. A second 64 bit number represents the tasks which have been completed:

$pack_code = 1001111100100000000000000011111101001111100100000000000000011111
$veri_code = 0000000000000000000000000001110000000000000000000000000000111110

I need to compare the two and provide a percentage of tasks completed figure. I could loop through both and find how many bits are set, but I开发者_如何学C don't know if this is the fastest way?


Assuming that these are actually strings, perhaps something like:

$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


Because you're getting the numbers as hex strings instead of ones and zeros, you'll need to do a bit of extra work.

PHP does not reliably support numbers over 32 bits as integers. 64-bit support requires being compiled and running on a 64-bit machine. This means that attempts to represent a 64-bit integer may fail depending on your environment. For this reason, it will be important to ensure that PHP only ever deals with these numbers as strings. This won't be hard, as hex strings coming out of the database will be, well, strings, not ints.

There are a few options here. The first would be using the GMP extension's gmp_xor function, which performs a bitwise-XOR operation on two numbers. The resulting number will have bits turned on when the two numbers have opposing bits in that location, and off when the two numbers have identical bits in that location. Then it's just a matter of counting the bits to get the remaining task count.

Another option would be transforming the number-as-a-string into a string of ones and zeros, as you've represented in your question. If you have GMP, you can use gmp_init to read it as a base-16 number, and use gmp_strval to return it as a base-2 number.

If you don't have GMP, this function provided in another answer (scroll to "Step 2") can accurately transform a string-as-number into anything between base-2 and 36. It will be slower than using GMP.

In both of these cases, you'd end up with a string of ones and zeros and can use code like that posted by @Mark Baker to get the difference.


Optimization in this case is not worth of considering. I'm 100% sure that you don't really care whether your scrip will be generated 0.00000014 sec. faster, am I right? Just loop through each bit of that number, compare it with another and you're done.

Remember words of Donald Knuth:

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.


This code utilizes the GNU Multi Precision library, which is supported by PHP, and since it is implemented in C, should be fast enough, and supports arbitrary precision.

$pack_code = gmp_init("1001111100100000000000000011111101001111100100000000000000011111", 2);
$veri_code = gmp_init("0000000000000000000000000001110000000000000000000000000000111110", 2);

$number_of_different_bits = gmp_popcount(gmp_xor($pack_code, $veri_code));


$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";

Output:

00000000000000000010101101100111
00000000000000000011000000111001
00000000000000000010000000100001
3

Given your PHP-setuo can handle 64bit, this can be easily extended.

If not you can sidestep this restriction using GNU Multiple Precision

You could also split up the HEx-Representation and then operate on those coresponding parts parts instead. As you need just the local fact of 1 or 0 and not which number actually is represented! I think that would solve your problem best.

For example:

0xF1A35C and 0xD546C1

you just compare the binary version of F and D, 1 and 5, A and 4, ...

0

精彩评论

暂无评论...
验证码 换一张
取 消