【发布时间】:2019-03-30 06:50:42
【问题描述】:
我正在研究一个代码库,该代码库使用以下编码来指示带替换的采样:我们维护一个整数数组作为样本中位置和存在的指标,其中正整数表示一个位置在另一个数组中,负整数表示我们不应在此迭代中使用数据点。
例子:
data_points: [...] // Objects vector of length 5 == position.size()
std::vector<int> position: [3, 4, -3, 1, -2]
这意味着data_points 中的第一个元素应该到桶 3,第二个到桶 4,第四个到桶 1。
负值表示在本次迭代中我们不会使用这些数据点,即第 3 和第 5 个数据点被标记为已排除,因为它们的位置值为负并且已使用position[i] = ~position[i] 设置。
诀窍是我们可能会多次执行此操作,但索引中数据点的位置不应该改变。所以在下一次迭代中,如果我们想要排除数据点 1,并包含数据点 5,我们可以这样做:
position[0] = ~position[0] // Bit-wise complement flips the sign on ints and subtracts 1
position[4] = ~position[4]
这会将位置向量变为
std::vector<int> position: [-4, 4, -3, 1, 1]
现在问题是:在每一轮结束时,我想将所有符号重置为正数,即位置应该变为 [3, 4, 3, 1, 2]。
是否有一个小技巧可以让我在没有值符号的 if 条件的情况下执行此操作?
另外,因为我不熟悉这样的位摆弄,为什么/如何采用带符号的正整数的位补码给我们它的数学补码? (即翻转符号的相同值)
编辑:以上是错误的, a (int) 的补码将给出 -(a + 1) 并取决于答案中指出的整数的表示。所以简单地取现有值的正值的原始问题不适用,我们实际上需要执行按位补码才能得到原始值。
例子:
position[0] = 1
position[0] = ~position[0] // Now position[0] is -2
// So if we did
position[0] = std::abs(position[0]) // This is wrong, position[0] is now 2!
// If we want to reset it to 1, we need to do another complement
position[0] = ~position[0] // Now position[0] is again 1
【问题讨论】:
-
当您可以使用
position[0] = -position[0]而不是position[0] = ~position[0]时,您想要在位级别上工作的任何特定原因? -
这不能回答你的问题,但你正在以一种有点复杂的方式使用负值。就个人而言,我会用一个布尔向量
should_use_bucket来表示它。然后您可以在每轮处理结束时清除布尔值。 -
是关于性能,你想避免分支?
-
我会选择
std::abs。 -
感谢所有 cmets。我也不喜欢像这样使用位置向量,但这是一个我正在贡献的大型代码库,我正在努力将更改保持在最低限度。
标签: c++ bit-manipulation