你所不知道的补码

某君不无兴奋地跟我说他有个重大发现: java里最小负整数的绝对值等于它本身! 程序员朋友可以试试以下判断:

Math.abs(int.MIN_VALUE) == int.MIN_VALUE

不管怎样, 取绝对值后一定是个正数, 怎么可能等于一个负数呢.乍一看, 太二和尚摸不着头脑. 向来以精准著称计算机世界, 怎么会得出如此可笑的结论?

其中一定有什么隐情! 凭直觉, 这应该和补码有关. 补码, 初中时代的知识, 不出意外地, 忘得差不多了, 先温故一下, 没准能知新.

正数的补码等于它自己, 负数的补码等于其反码+1.

计算机是以二进制方式表示数字的, 其中负数又以补码的方式表示. 当回忆起这点的时候, 有一个问题吸引了我:为什么负数要用补码表示呢?, 这似乎是一个和1+1为什么等于2一样傻的问题, 所以当年聪明的我没敢问老师为什么. 如今智商越发下降, 类似的问题也越来越多, 然后, 像小孩子发现更好玩的玩具一样, 开头那个问题就被晾在一边了…

大概一开始人们也没设计出补码这玩意儿, 毕竟谁会上来就找麻烦搞这么复杂的东西. 应该是很自然地第一位是符号位, 0表示正数, 1表示负数, 剩下是表示值的多少. 当然, 对于人类轻而易举想到的答案, 上帝一般是要发笑的. 这个方案会有什么问题呢? 让我们简单地假定整数是用3个比特表示的, 其表示的所有数字, 排列组合如下:

000: 0, 001: 1, 010: 2, 011: 3, 100: -0, 101: -1, 110: -2, 111: -3

这样也能work. 但很显然的不足是, 0有两种表示法, 有点浪费空间了. 还有一个更隐蔽的缺点, 用一道题来说明. 按上述规则计算下1-1, 也就是1+(-1)的结果.

001+101=110

110就是-2, 显然不对. 那么如何设计才能让同时弥补上述两个缺点呢? 这时候, 补码就隆重登场了. 按补码的规则重新穷举上述排列:

000: 0, 001: 1, 010: 2, 011: 3, 100: -4, 101: -3, 110: -2, 111: -1

0不再重复了, 表示的空间从[-3, 3], 扩大到[-4, 3]. 而且1-1的计算, 变得简单自然, 丝般顺滑(最高位溢出):

001+111=000

因此, 不必为加法和减法设计两套计算电路! 两个看似不同, 甚至对立的逻辑, 得到了统一. 设计之巧妙, 令人叹服. 看似很傻的问题, 细细研究, 原来这般微妙, 优雅得简直像艺术品, 不得不佩服提出补码那位兄台.

绕了个圈, 回到最开始的问题. 绝对值的计算大家都清楚: 正数, 直接返回它自己, 负数, 返回其相反数. 而java计算相反数, 就是取其补码. 仍然拿3比特的为例, 最小的负数是100(-4), 取反是011, 加1后是100, 还是-4. int类型一般是32比特, 但演算过程是一样的.

写代码如何能少出bug? 做架构如何能更灵活适应需求的变化? 一个共同的答案是, 发现和归纳事物的规律, 通过巧妙的设计, 或更高的抽象, 减少差异性, 提高普适性.

设计行业里流行少即是多的理念. 我想, 少不是刻意删除, 不是空洞无物. 少, 是在充分理解的前提下, 找到那个支点, 四两拨千斤, 用最小的付出, 撬动最大的收益. 九九归一, 少得下来, 一定是看透了规律, 抓住了本质.

上面对补码的理解, 足够概括和普适了吗? 并没有.

先试试在进制上做点延展. 小学生都会的减法, 能否统一成加法呢? 答案是肯定的. 事实上,

两整数 A、B 用同一个正整数 M (M 称为模)去除而余数相等,则称 A、B 对 M同余,记作: A=B (MOD M). 具有同余关系的两个数为互补关系,其中一个称为另一个的补码.

那么, 一个更加概括的理解是:减去一个数, 等于加上这个数的补码.

数学源于生活, 让我们举个日常生活的例子. 时钟连3岁小孩都能看懂, 比11点早3小时是8点, 比11点晚9小时也是8点, 嘿嘿, 说的就是这个理, 只不过这里的模是12. 而计算机用的是二进制, 以2为模: 1-1 = 1+1 = 2+0 = 0 (2被抹掉了).

所以下回教小孩子做减法可以这么说: 7-3 = 7+7 = 10+4 = 4. 当然, 要解释为什么10被任性地抹掉了, 也挺费劲.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容

  • 网站乱码问题我们会经常碰到,大多见于非英文的中文字符或其他字符乱码,而且,这类问题常常是因为编码方式问题,主要原因...
    波段顶底阅读 2,857评论 1 9
  • 本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可...
    yang2yang阅读 2,246评论 1 13
  • 前些日子,抽空做了一下所谓的微3D效果的控件,然后我给他取名叫JECalourseView,由于本人比较忙,比比较...
    一个野指针阅读 3,417评论 4 8
  • 图/木槿 文/木槿 春花秋月 夏日冬雪 极美、醉人情 一轮逍遥游历 来日暖席煮酒 索然心事愁欢 痴缠千幕景 留恋万...
    痴人一念阅读 258评论 2 18
  • 一个女人的自述 我想我就是个名副其实的“破鞋”吧。从我毕业到现在八年了,我有过六个男朋友,还有一个旅行是遇见的“艳...
    可怜人Loser阅读 8,474评论 2 0