整数在内存中的存储形式。。
2016-07-23 12:25
253 查看
真大神啊。。。。瞬间理解:
source:http://bbs.chinaunix.net/thread-3765224-1-1.html
很对, 没有问题. 不过我想告诉LZ一个更容易理解的办法.
假设, 我现在只有4 bits空间. 那么这个空间最多能存放2 ^ 4, 即16个数, 也就是 0 - 15.
想像一个表盘, 这个表盘刚好有16个刻度. 这样子, 我们将上面的16个数和表盘对应起来. 对应的结果如下所示.
|
|
0000
1111 0001
1110 0010
1101 0011
1100 0100
1011 0101
1010 0110
1001 0111
1000
|
|
本来表盘是圆形的, 结果上面看上去是菱形的. 将就看吧.
瞧: 这个表盘能够表示16个数字, 所以我们称呼16为这个表盘的模. 同理, 我们称16是4bits的模, 256是8bits的模, etc.
看到上面和下面我分别标的竖线了吗? 那代表我将这个表盘切成了两部分.
这个切法代表什么意思呢?
我们知道表盘能够表示16个数字, 如果我认为这个表盘表示的数字都是正数, 那么我可以不切这个表盘. 不切这表盘就表示, 假设时针从0开始顺时针转, 每过一个小时, 时针就向前一格(假设一天有16个小时, 这也不是什么大事, 呵呵). 于是, 这个表盘可以表示 0 -- 15.
现在我想让这个表盘既可以表示正数, 也可以表示负数. 看, 很简单, 我把这个表盘像上面那样切开, 就像切一个馅饼一样. 我说左半部分你们代表正数吧. 右半部分你们代表负数吧. 于是一切就work了, 我们让时针顺时针转, 顺时针走一格就代表加1. 我们让时钟逆时针转, 逆时针走一格就代表减1.瞧,
正着转一格, 0000 -> 0001. 逆时针转一格, 0000 -> 1111, 等等, 1111是什么? 没错, 1111就是补码的-1. 看, 这个表盘完美地工作, 太妙了.
现在我们来做一件事情. 假设现在时针指向12点(注意, 我们这个表盘一共有16点), 就是指向1100那里. 现在我们想让时钟指到9点, 也就是1001那里. 我们可以用两种方式来做到这一点:
第一种方式是倒拨(逆时针方向)3格.
于是我们有: 12 - 3 = 9.
第二种方式是顺拨13格.
于是我们有: 12 + 13 = 9.
我们看看, -3是谁? 假设我们切开了这个表盘, 那么-3就是1101.
我们再看看, 13是谁? 假设我们没有切开这个表盘, 看, 13也是1101.
于是我们有: 1100 + 1101 = 1001
于是, 明白了吗, 我不需要12 - 3, 那个减号对我来说没用. 我只管知道 1100 + 1101 = 1001就可以了. 没错, 计算机为什么用补码来表示整数,因为用补码来表示整数不需要减法, 我们只要一个硬件加法器就可以了.
同时, 我们还发现一件事情.
(12 - 3) % 16 == 9
(12 + 13) % 16 == 9
我们称, 12 - 3 和 12 + 13 共模同余(模16余9), 同时称, 13和3互补(在模为16的前提下), 即互为补数. 看, 算补码也很简单了.
当然了, 比如假设有32 bits, 那么模就是2 ^ 32, 如果有64 bits, 那么模就是 2 ^ 64. 很简单, 我们只需要想象一个大得多的表盘就可以了, 这挺简单的, 不是吗?
source:http://bbs.chinaunix.net/thread-3765224-1-1.html
很对, 没有问题. 不过我想告诉LZ一个更容易理解的办法.
假设, 我现在只有4 bits空间. 那么这个空间最多能存放2 ^ 4, 即16个数, 也就是 0 - 15.
想像一个表盘, 这个表盘刚好有16个刻度. 这样子, 我们将上面的16个数和表盘对应起来. 对应的结果如下所示.
|
|
0000
1111 0001
1110 0010
1101 0011
1100 0100
1011 0101
1010 0110
1001 0111
1000
|
|
本来表盘是圆形的, 结果上面看上去是菱形的. 将就看吧.
瞧: 这个表盘能够表示16个数字, 所以我们称呼16为这个表盘的模. 同理, 我们称16是4bits的模, 256是8bits的模, etc.
看到上面和下面我分别标的竖线了吗? 那代表我将这个表盘切成了两部分.
这个切法代表什么意思呢?
我们知道表盘能够表示16个数字, 如果我认为这个表盘表示的数字都是正数, 那么我可以不切这个表盘. 不切这表盘就表示, 假设时针从0开始顺时针转, 每过一个小时, 时针就向前一格(假设一天有16个小时, 这也不是什么大事, 呵呵). 于是, 这个表盘可以表示 0 -- 15.
现在我想让这个表盘既可以表示正数, 也可以表示负数. 看, 很简单, 我把这个表盘像上面那样切开, 就像切一个馅饼一样. 我说左半部分你们代表正数吧. 右半部分你们代表负数吧. 于是一切就work了, 我们让时针顺时针转, 顺时针走一格就代表加1. 我们让时钟逆时针转, 逆时针走一格就代表减1.瞧,
正着转一格, 0000 -> 0001. 逆时针转一格, 0000 -> 1111, 等等, 1111是什么? 没错, 1111就是补码的-1. 看, 这个表盘完美地工作, 太妙了.
现在我们来做一件事情. 假设现在时针指向12点(注意, 我们这个表盘一共有16点), 就是指向1100那里. 现在我们想让时钟指到9点, 也就是1001那里. 我们可以用两种方式来做到这一点:
第一种方式是倒拨(逆时针方向)3格.
于是我们有: 12 - 3 = 9.
第二种方式是顺拨13格.
于是我们有: 12 + 13 = 9.
我们看看, -3是谁? 假设我们切开了这个表盘, 那么-3就是1101.
我们再看看, 13是谁? 假设我们没有切开这个表盘, 看, 13也是1101.
于是我们有: 1100 + 1101 = 1001
于是, 明白了吗, 我不需要12 - 3, 那个减号对我来说没用. 我只管知道 1100 + 1101 = 1001就可以了. 没错, 计算机为什么用补码来表示整数,因为用补码来表示整数不需要减法, 我们只要一个硬件加法器就可以了.
同时, 我们还发现一件事情.
(12 - 3) % 16 == 9
(12 + 13) % 16 == 9
我们称, 12 - 3 和 12 + 13 共模同余(模16余9), 同时称, 13和3互补(在模为16的前提下), 即互为补数. 看, 算补码也很简单了.
当然了, 比如假设有32 bits, 那么模就是2 ^ 32, 如果有64 bits, 那么模就是 2 ^ 64. 很简单, 我们只需要想象一个大得多的表盘就可以了, 这挺简单的, 不是吗?
相关文章推荐
- 从web专业角度谈谈如何对screen设备宽度断点
- 5、整合Drools5.4.0+Spring+maven
- Contains Duplicate
- uboot中利用TFTP和NFS加载内核镜像和根文件系统
- Springboot jpa 解决Mysql8小时问题
- 高效编程之互斥锁和自旋锁的一些知识
- Appium Android 屏幕滑动
- codeforces 701C C. They Are Everywhere(尺取法)
- Radar Installation
- VMware虚拟机配置Ubuntu桥接方式(Bridged)使虚拟机和宿主机能互相ping通
- 图形验证码笔记
- FFmpeg编程初步
- RedHat Linux 挂载U盘
- PAT-B 1015. 德才论
- 修改APK包并push到system/app路径下安装
- Shell脚本中执行mysql的几种方式(转)
- Sumsets
- maven + redis + 分布式锁
- Hibernate---QBC查询(1)
- 扩展KMP模板