【发布时间】:2016-10-28 17:29:58
【问题描述】:
正如Given three numbers, find the second greatest of them 的建议解决方案,我写道:
int second_largest(int a, int b, int c) {
int smallest = min(min(a, b), c);
int largest = max(max(a, b), c);
/* Toss all three numbers into a bag, then exclude the
minimum and the maximum */
return a ^ b ^ c ^ smallest ^ largest;
}
这个想法是^ smallest ^ largest 取消了这些位,以便保留中间数字。
不过,@chux 指出了一个问题:
int和a ^ b ^ c ^ smallest ^ largest的一个独特问题是中间结果可能是罕见的非 2 补码平台上的陷阱表示。 – chux@chux 请解释一下? XOR 只是逐位运算,并不关心位代表什么,对吧? – 200_成功
XOR 不关心,但结果可能有问题:例如使用符号大小整数,
-1 ^ 1转到-0,这可能是一个陷阱值 - 停止代码。参见 C11 §6.2.6.2 2. 位运算更好地用于无符号类型。 – chuxFurther C11 §6.2.6.2 3 在罕见的非 2 的补码平台上指定 ^ 的实现定义行为 int 。特别是“未指定这些情况是否实际生成负零或正常零”,呈现 a ^ b ^ c ^ minimum ^ maximum 未指定即使不使用陷阱值它也会按需要工作。下一节将解释这如何成为 UB。最好将这个新颖的代码留给无符号类型。 – chux
令人遗憾的是,本应在逻辑和数学上合理的技术可能会因技术问题而脱轨。
有没有办法挽救这种 XOR 技术并使其在法律上安全,理想情况下运行时开销为零? (可能涉及工会的事情?)
【问题讨论】:
-
请注意,这不是 XOR 独有的 - 相同的参数可以应用于任何位运算符。
-
您只需要三个比较即可获得三个中第二大的比较。这比前两行中的多重比较差多少?
-
我会做三个比较并将结果编码为索引,然后将逻辑实现为 8-case 开关。
-
“有没有办法挽救这种 XOR 技术”对我来说,在此之前的第一个问题应该是 是否有任何理由挽救这种技术? ...我没有看到。至于“一种应该在逻辑上和数学上合理的技术”,这假设(A)数学关心位表示,(B)语言标准化用于存储这些值的表示,并且(C)两者都同意这一点。这些都不是真的。为什么不只使用数学运算符并正确使用它,而不是搞乱位操作(我喜欢,但似乎对此并不相关/有用)
-
@underscore_d 除了陷阱表示问题之外,此技术工作的唯一其他要求是位集合(例如
0x2545f28a)在a、b中意味着相同的事情,c就像在smallest或largest中一样。位代表什么无关紧要,只要它是一致的,以便位抵消。
标签: c c99 undefined-behavior bitwise-xor signed-integer