在一个补充平台上,下面的代码会打印什么?
#include <iostream>
int main() {
int i = 1, j = -1;
std::cout << i+j << std::endl;
return 0;
}
我怀疑它会打印“0”而不是“-0”,但我似乎找不到任何权威的东西。
编辑为了澄清,我对如何打印-0感兴趣,有几个人建议在实践中,使用上述代码执行one-compliment可能不会产生负零
在这些情况下,建议以下实际生成-0:
#include <iostream>
int main() {
std::cout << ~0 << std::endl;
return 0;
}
问题仍然存在:这会打印什么?
答案 0 :(得分:5)
确实将n
添加到-n
应该给你一个负零。但是-0的生成在实践中并没有发生,因为1的补码加法使用了一种称为补充减法器的技术(第二个参数补充并从第一个减去)。 / p>
(获得有符号浮点零的惯用方法并不适用于此,因为您无法将整数除以零)。
答案 1 :(得分:5)
首先,为了澄清事情,使用按位运算制作负零,然后使用结果值是不可移植的。也就是说,fprintf
(因此,std::basic_ostream::operator<<(int)
)的文档中没有指定int表示中的符号位是否对应于unsigned
或实际表示中的填充位价值位。
作为结论,这是未指明的行为。
#include <iostream>
int main() {
std::cout << ~0 << std::endl;
return 0;
}
答案 2 :(得分:5)
通过glibc源代码,我在vfprintf.c中找到了这些行:
532 is_negative = signed_number < 0; \
533 number.word = is_negative ? (- signed_number) : signed_number; \
534 \
535 goto LABEL (number); \
...
683 if (is_negative) \
684 outchar (L_('-')); \
因此,条件似乎为signed_number < 0
,对于-0
将返回false。
正如@Ysc所提到的,文档中没有任何内容给出了打印-0
的任何规范,因此libc的不同实现(在one-compliment上)可能产生不同的结果。
答案 3 :(得分:0)
如果我们看一个补语的理论观点。由于零定义为(+/-)0,如果我们有4个Bit值,则0将有两个二进制值,零为0000(+0)和1111(-0)。因此,如果操作,加法或减法操作中有过零操作,则必须进行校正。
因此,例如,如果我们执行以下操作-2+6=4
,结果将按如下方式计算:
1101 (-2)
+ 0110 (6)
------
1100 (add carry)
======
0011 (+3)
正如您在Bit操作中看到的那样,结果不正确,只是结果不完整。在这种情况下,我们必须为该值添加+1以获得正确的结果。要确定是否必须添加+1,我们必须查看添加进位结果。如果最左边的数字 1 100是一个,那么我们必须在结果中添加+1以获得正确的结果。
如果我们看一下你的例子:
0001 (+1)
+ 1110 (-1)
------
0000 (add carry)
======
1111 (-0)
我们看到结果将是-0,这将是最终结果,因为左侧的进位位为0。