按段比较 64 位整数
Compare 64-bit integers by segments
我有两个 64 位整数 x
和 y
。每一位代表5个无符号短整数:前10位代表第一个整数,接下来的13位代表第二个整数,接下来的16位代表第三个整数,接下来的14位代表第四个整数,其余位代表第 5 个整数。
设x0
、x1
、x2
、x3
、x4
为构成x
的5个短整数。设y0
、y1
、y2
、y3
、y4
为构成y
的5个短整数。我需要知道 x0 < y0
AND x1 < y1
AND x2 < y2
AND x3 < y3
AND x4 < y4
.
我假设最简单的解决方案是移动:
bool allLess(std::size_t x, std::size_t y)
{
if(x >= y) return 0;
int shift[] = {10, 13, 16, 14};
for(int i = 0; i < 4; ++i)
{
x <<= shift[i];
y <<= shift[i];
if(x >= y) return 0;
}
return 1;
}
我知道有很多按位体操。任何更快的解决方案?
这并没有真正回答所提出的问题,但解决了一个非常相似的问题:(如果有人能够重新组织实际问题,如 OP,这可能会有所帮助)
如果整数没有紧密排列(即如果每个 "field" 之间和 MSB 末尾有单个零位填充),并且您想知道 <=
而不是 <
,我认为您可以只减去数字并检查是否有任何填充位发生变化。 (即 (y - x) & PADDING_MASK
)
可以使用位域
#include <iostream>
#include <string.h>
#include <stdint.h>
struct CombInt64 {
CombInt64(uint64_t x) {
memcpy(this, &x, sizeof(uint64_t));
}
bool operator < (const CombInt64& other) const {
std::cout << "Debug: self.a: " << a << " other.a: " << other.a << std::endl;
std::cout << "Debug: self.b: " << b << " other.b: " << other.b << std::endl;
std::cout << "Debug: self.c: " << c << " other.c: " << other.c << std::endl;
std::cout << "Debug: self.d: " << d << " other.d: " << other.d << std::endl;
std::cout << "Debug: self.e: " << e << " other.e: " << other.e << std::endl;
return a < other.a && b < other.b && c < other.c && d < other.d && e < other.e;
}
#if __BYTE_ORDER == __LITTLE_ENDIAN
uint64_t a:10;
uint64_t b:13;
uint64_t c:16;
uint64_t d:14;
uint64_t e:11;
#elif __BYTE_ORDER == __BIG_ENDIAN
uint64_t e:11;
uint64_t d:14;
uint64_t c:16;
uint64_t b:13;
uint64_t a:10;
#endif
};
bool allLess(uint64_t x, uint64_t y) {
return CombInt64(x) < CombInt64(y);
}
int main(void) {
std::cout << allLess(123, 45) << std::endl;
}
输出
[root@localhost tmp]# ./a.out
Debug: self.a: 123 other.a: 45
Debug: self.b: 0 other.b: 0
Debug: self.c: 0 other.c: 0
Debug: self.d: 0 other.d: 0
Debug: self.e: 0 other.e: 0
0
未完全测试!!!
我有两个 64 位整数 x
和 y
。每一位代表5个无符号短整数:前10位代表第一个整数,接下来的13位代表第二个整数,接下来的16位代表第三个整数,接下来的14位代表第四个整数,其余位代表第 5 个整数。
设x0
、x1
、x2
、x3
、x4
为构成x
的5个短整数。设y0
、y1
、y2
、y3
、y4
为构成y
的5个短整数。我需要知道 x0 < y0
AND x1 < y1
AND x2 < y2
AND x3 < y3
AND x4 < y4
.
我假设最简单的解决方案是移动:
bool allLess(std::size_t x, std::size_t y)
{
if(x >= y) return 0;
int shift[] = {10, 13, 16, 14};
for(int i = 0; i < 4; ++i)
{
x <<= shift[i];
y <<= shift[i];
if(x >= y) return 0;
}
return 1;
}
我知道有很多按位体操。任何更快的解决方案?
这并没有真正回答所提出的问题,但解决了一个非常相似的问题:(如果有人能够重新组织实际问题,如 OP,这可能会有所帮助)
如果整数没有紧密排列(即如果每个 "field" 之间和 MSB 末尾有单个零位填充),并且您想知道 <=
而不是 <
,我认为您可以只减去数字并检查是否有任何填充位发生变化。 (即 (y - x) & PADDING_MASK
)
可以使用位域
#include <iostream>
#include <string.h>
#include <stdint.h>
struct CombInt64 {
CombInt64(uint64_t x) {
memcpy(this, &x, sizeof(uint64_t));
}
bool operator < (const CombInt64& other) const {
std::cout << "Debug: self.a: " << a << " other.a: " << other.a << std::endl;
std::cout << "Debug: self.b: " << b << " other.b: " << other.b << std::endl;
std::cout << "Debug: self.c: " << c << " other.c: " << other.c << std::endl;
std::cout << "Debug: self.d: " << d << " other.d: " << other.d << std::endl;
std::cout << "Debug: self.e: " << e << " other.e: " << other.e << std::endl;
return a < other.a && b < other.b && c < other.c && d < other.d && e < other.e;
}
#if __BYTE_ORDER == __LITTLE_ENDIAN
uint64_t a:10;
uint64_t b:13;
uint64_t c:16;
uint64_t d:14;
uint64_t e:11;
#elif __BYTE_ORDER == __BIG_ENDIAN
uint64_t e:11;
uint64_t d:14;
uint64_t c:16;
uint64_t b:13;
uint64_t a:10;
#endif
};
bool allLess(uint64_t x, uint64_t y) {
return CombInt64(x) < CombInt64(y);
}
int main(void) {
std::cout << allLess(123, 45) << std::endl;
}
输出
[root@localhost tmp]# ./a.out
Debug: self.a: 123 other.a: 45
Debug: self.b: 0 other.b: 0
Debug: self.c: 0 other.c: 0
Debug: self.d: 0 other.d: 0
Debug: self.e: 0 other.e: 0
0
未完全测试!!!