如果你这样做是为了学习编程,你可以做一些编程来帮助你确认答案:
#include <iostream>
int abs(int x) { return x >= 0 ? x : -x; }
int main()
{
for (int i = -128; i <= 127; ++i)
{
char x = i;
char y;
if (x > 0)
y = x;
else
y = -x;
if (!(y >= 0 && abs(y) == abs(x)))
std::cout << "failed for " << i << " (y " << (int)y << ")\n";
}
}
运行这个你会看到 -128 是否失败x
(其中y
是 -128)。这是由于 2 的补码表示法的不对称性:-128 可以用 8 位字符表示,但 128 不能(只有 127)。
因此,对于 1,并假设 2 的补码整数,前提条件是它x
不是您的位宽中的最低可表示值。当然,问题中没有任何内容说 x 和 y 是偶数,所以这有点试探性。
如果x
andy
是浮点数或双精度数,那么在正常的 IEEE 表示中,有一个符号位可以在不影响尾数或指数的情况下进行切换,从而允许符号的“干净”变化。也就是说,也存在“非数字”(NaN)和(正和负)无穷大标记值的极端情况,明智的做法是通过实验和/或通过研究表示和行为规范来检查......
描述为什么 [{ y >= 0 && |y| == |x| }] 比 { y >= 0} 更适合验证代码。
一个模糊的问题,因为我们不确定代码试图实现什么,我们对此的推理循环来自断言前一个后置条件优于后者。尽管如此,他们仍在寻找这样的答案:y
无论代码对x
.
在实践中,对于我们的 2 的补码整数,幅度在之后总是匹配 - 它是标记极端情况的后置条件的符号部分。但是,对预期的内容有额外的洞察力仍然令人放心。