您已经有了一个聪明的答案:无符号算术是模算术,因此结果将保持不变,您可以用数学方式证明它……
但是,关于计算机的一件很酷的事情是计算机速度很快。确实,它们是如此之快,以至于在合理的时间内可以枚举32位的所有有效组合(请勿尝试使用64位)。
因此,就您而言,我个人喜欢将其扔到计算机上。与说服自己而不是数学证明是正确的,让我说服自己的时间相比,让我花费更少的时间,并且我没有监督规范1中的细节:
#include <iostream>
#include <limits>
int main() {
std::uint64_t const MAX = std::uint64_t(1) << 32;
for (std::uint64_t i = 0; i < MAX; ++i) {
for (std::uint64_t j = 0; j < MAX; ++j) {
std::uint32_t const a = static_cast<std::uint32_t>(i);
std::uint32_t const b = static_cast<std::uint32_t>(j);
auto const champion = (a + (b & 255)) & 255;
auto const challenger = (a + b) & 255;
if (champion == challenger) { continue; }
std::cout << "a: " << a << ", b: " << b << ", champion: " << champion << ", challenger: " << challenger << "\n";
return 1;
}
}
std::cout << "Equality holds\n";
return 0;
}
此枚举通过的所有可能值a
,并b
在32位空间并检查是否等号成立,或没有。如果没有,它将打印出无效的案件,您可以将其用作健全性检查。
而且,根据Clang所说:平等成立。
此外,假定算术规则是位宽度不可知的(int
位宽度以上),则此等价关系适用于32位或更多(包括64位和128位)的任何无符号整数类型。
注意:编译器如何在合理的时间范围内枚举所有64位模式?这不可以。循环进行了优化。否则,我们将在执行终止之前全部死亡。
最初,我仅针对16位无符号整数证明了这一点。不幸的是,C ++是一种疯狂的语言,其中小整数(位宽小于int
)首先被转换为int
。
#include <iostream>
int main() {
unsigned const MAX = 65536;
for (unsigned i = 0; i < MAX; ++i) {
for (unsigned j = 0; j < MAX; ++j) {
std::uint16_t const a = static_cast<std::uint16_t>(i);
std::uint16_t const b = static_cast<std::uint16_t>(j);
auto const champion = (a + (b & 255)) & 255;
auto const challenger = (a + b) & 255;
if (champion == challenger) { continue; }
std::cout << "a: " << a << ", b: " << b << ", champion: "
<< champion << ", challenger: " << challenger << "\n";
return 1;
}
}
std::cout << "Equality holds\n";
return 0;
}
再次,根据锵:等式成立。
好吧,你去了:)
1 当然,如果程序无意中触发了“未定义行为”,那就证明不了什么。
Math.random()
在[0,1)上返回整数或双精度数?我认为您的脚本(我能说的最好)根本无法反映您提出的问题。