std:比较不可代表数字的映射技巧
std::map trick for comparing unrepresentable numbers?
我希望在C++std::map
中有一个用户定义的键。密钥是具有最大值2^V
的整数集的二进制表示,因此我不能表示所有2^V
可能的值。我通过一个有效的二进制集表示,即uint64_t
的数组来做到这一点。
现在的问题是,要将这个用户定义的位集作为std::map
中的密钥,我需要定义位集值之间的有效比较,但如果我的最大大小为,例如V=1000
,那么我就无法获得可以比较的数字,更不用说将它们全部聚合了,即2^1000
是不可表示的。
因此,我的问题是,假设我有两个不同的集合(通过在我的比特集表示中设置正确的比特),并且我不能表示最终的数字,因为它会溢出:
id_1 = 2^0 + 2^1 + ... + 2^V
id_2 = 2^0 + 2^1 + ... + 2^V
是否有一个合适的转换可以产生一个我可以比较的值?我需要能够说id_1 < id_2
,所以我想把指数的和转换成一个可表示的值,但保持"小于"的不变量。我的思路是,例如,以一种巧妙的方式应用日志转换来保存"小于"。
这里有一个例子:
set_1 = {2,3,4}; set_2 = {8}
id(set_1) = 2^2 + 2^3 + 2^4 = 28; id(set_2) = 2^8 = 256
id(set_1) < id(set_2)
完美!一个可以有{1,...,V}
,从而有2^V
可能子集的一般集合怎么样?
我通过一个有效的二进制集表示来实现这一点,即uint64_t的数组。
假设这个数组是通过密钥类型为Key
的数据成员ra
访问的,并且两个数组的长度都是N
,那么您需要一个类似这样的比较器:
bool operator<(const Key &lhs, const Key &rhs) {
return std::lexicographical_compare(lhs.ra, &lhs.ra[N], rhs.ra, &rhs.ra[N]);
}
这隐含地认为数组是大端序,即第一个uint64_t
是最重要的。如果你不喜欢,那就足够了,因为你可能已经考虑到了将V
位存储到数组中的任何顺序的相对重要性。lexicographical_compare
没有什么神秘之处,所以只需查看一个示例实现并根据需要进行修改即可。
这被称为"字典序"。除了我使用了uint64_t
而不是char
,并且两个数组的长度相同之外,这就是字符串的比较方式[*]——事实上,uint64_t
的使用并不重要,你可以在比较器中使用std::memcmp
,而不是比较64位块。字符串的operator<
不能通过将整个字符串转换为整数来工作,比较器也不应该。
[*],直到您使用特定于区域设置的排序规则。
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 检查输入是否不是整数或数字
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 将函数类成员映射到类本身内部
- 如何在 C# 中映射双 C 结构指针?
- 如何在C++中使用结构生成映射
- 使用std::函数映射对象方法
- 如何加载(或映射)文件部分的最大大小,但适合在Windows上的RAM
- C++映射分割错误(核心转储)
- 将一系列数字映射到 CPP 中的值的简单方法
- 将大数字(10-12 位数字)存储在无序映射中<字符串,整数>
- 将映射的每个键中的数字数据与另一个数值进行比较
- 如何将3个数字映射到值(动态编程)
- std:比较不可代表数字的映射技巧
- c++将大型数字字符串映射到数字字符串范围
- 将 1 到 12 之间的数字映射到月份名称
- 以将阵列中的数字范围映射为均匀随机1到100