std::cout如何在一补系统中打印负零?
How does std::cout print negative zero in a ones-complement system?
在one -complement平台上,下面的代码将打印什么?
#include <iostream>
int main() {
int i = 1, j = -1;
std::cout << i+j << std::endl;
return 0;
}
我怀疑它会打印"0"而不是"-0",但我似乎找不到任何权威的。
编辑:为了澄清,我对如何打印-0感兴趣,有几个人建议在实践中,ones-compliment的实现可能不会使用上述代码生成负零。
在这些情况下,建议使用以下方法实际生成-0:
#include <iostream>
int main() {
std::cout << ~0 << std::endl;
return 0;
}
问题仍然存在:这将打印什么?
首先,为了澄清一点,使用按位操作生成一个负零,然后使用结果值是不可移植的。也就是说,在fprintf
(也就是std::basic_ostream::operator<<(int)
)的文档中没有指定int表示中的符号位是否对应于unsigned
表示中的填充位或实际值位。
作为结论,这是未指定的行为。
#include <iostream>
int main() {
std::cout << ~0 << std::endl;
return 0;
}
确实,将n
添加到-n
应该得到负零。但是在实际中不会生成-0,因为1的补加法使用了一种称为补减法的技术(第二个参数是第一个参数的补和减)。
(获得有符号浮点零的惯用方法在这里不适用,因为不能将整数除以零)。
查看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平台上)可能会产生不同的结果。
如果我们从补语的理论角度来看。由于零被定义为(+/-)0,因此0将有两个二进制值,如果我们有4位值,则零将是0000(+0)和1111(-0)。因此,如果加法或减法运算中有过零操作,则必须进行修正。
因此,如果我们执行以下操作-2+6=4
,结果将计算如下:
1101 (-2)
+ 0110 (6)
------
1100 (add carry)
======
0011 (+3)
正如您在Bit操作中看到的,结果是不正确的,只是不完整的结果。在这种情况下,我们必须在值上加上a +1才能得到正确的结果。为了确定+1是否要加,我们必须看一下加进的结果。如果最左边的数字1100是1,那么我们必须在结果上加1才能得到正确的结果。
如果我们看一下你的例子:
0001 (+1)
+ 1110 (-1)
------
0000 (add carry)
======
1111 (-0)
我们看到结果将是-0,这将是最终结果,因为左加进位为0。
- 如何循环打印顶点结构
- 为什么在popback()操作之后,它仍然打印完整的矢量
- C++,系统无法执行指定的程序
- 如何在c++中打印目录
- 在UNIX系统中使用DIR查找文件的字节大小
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 在线编译器中的分段C++没有打印消息
- 如何使系统在十六进制数之前打印 0x,在八进制数之前打印 0?
- 如何从文件系统打印特定名称文件
- c++ GDI 打印导致系统冻结
- 将系统命令打印到文本文件 C++
- 如何在Windows日语系统中打印日语字符
- 该程序不会在任何地方打印系统日志?
- C++11打印当前系统时间(包括毫秒)
- 使用Windows技术检测复制,粘贴,打印系统命令
- EXECLP系统调用不打印到标准输出
- 使用 c++ chrono 以纳秒为单位打印当前系统时间
- 无法通过系统注册表中的递归打印子项的子项
- std::cout如何在一补系统中打印负零?
- 防止打印结束后系统超时