补码
2020.3 update: 这段文字是我2018年10月大一的时候写的,当时大概在程设课上想到,以为自己发现了什么新大陆。但其实,这无非是补码的原理在我们的计算机教学中没有体现的缘故,这里所讲所想的,在Computer System: A Programmer's Perspective这本计算机系统科普入门书的第2章 Representing and Manipulating Information里都有提到,而且讲解更仔细。一年后发现我这篇短文章的阅读量竟然不小,可见中文互联网对优秀内容的需求还是很大的。重读当时的文字,感觉当时写的基本原理都是对的,只是行文很不流畅,留下青涩的痕迹,排版也有错漏。在此打磨一下。
===========================================================================我是分割线=
C++里面带符号整数类型(例如int)对负数的二进制存储是用补码进行的.对补码的解释一般是"对负数的绝对值按位取反再+1".
不过我觉得"按位取反再+1"只是用到补码的时候一种正确的求法.
更符合补码的原理,对补码更加自然的解释是:对于负数,"若数据类型为n个二进制位,则补码为".也就是说,这个补码其实就是,只不过是对取模之后的.这样就能理解,为什么减去一个数等于加上这个数的补码,因为补码无非是这个数在模意义下的相反数.
自行验证一下,按位取反再+1和的结果是完全一样的. 这是因为按位取反就相当于.
#include<cstdio>
int main(){
unsigned int a = -1;
printf("%d\n",a);
printf("%u\n",a);
printf("%x\n",a);
return 0;
}
unsigned int a = -1
这个赋值语句首先要把-1转化为二进制补码表示,然后把这串补码表示的二进制数直接赋值给a,赋给a的值当然就是.
printf("%d\n",a)
却能完美地输出-1.
这里涉及到int如何分辨正数和负数.int有32个二进制位,用最高位分辨正负.如果最高位为1,就是负数,最高位为0,就是正数(或者0).
int存储范围是 我们把负数(-x)都用补码表示,也就是说用表示这个范围的整数.可以看到,这个范围的数字得到的补码恰好都是最高位为1的.(的补码是"最小"的补码,只有最高的二进制位是1,其他二进制位都是0,而-1的补码所有二进制位都是1).而int能表示的最大正数,就是令最高位为0,其他数位都是1.
0的补码仍为0,所以补码表示法解决了0的正负问题.
回过头来看那段代码,printf("%d\n",a)
里面的%d把a的二进制表示按照int类型解释,自然就解释出了-1的值,输出结果是-1.
总结一下,int补码表示法的的本质是在模2的n次方的意义下表示负数(n通常为32), 也就是把 表示为
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
2016-10-15 Bzoj3663/4660 CrazyRabbit