幽灵 发表于 2023-4-23 14:59

0x01 原码、反码、补码

这里说的是在计算机中我们使用的十进制数,为何一旦超过一定的范围,他就会从正数变为负数,以及在计算机中,正数,负数的存储

# 存储规则

- 数据在内存中是以二进制补码的形式存储
- 在有符号数中,最高位为符号位,0为正数,1为负数
- 正数的原码、反码、补码都是它本身(这里都是转化为二进制的)
- 负数的反码:符号位不变,对原码其它位依次取反,就是0变1,1变0
- 负数的补码:符号位不变,反码+1

举例子
以 8 bit 的数据存储为例子

```
+10 // 正整数 10
原码 00001010// 1010 不够8位,在前面补0,最高位0表示正数
反码 00001010
补码 00001010// 这个是在内存中存储的

-10 // 负正数 10
原码 10001010// 最高位是1,表示负数
反码 11110101// 负数反码,在除了最高位外全部取反
补码 11110110// 在反码的基础上+1,这个也是在内存中存储的负数
```

# 三种码之间的转换

这里只是做负数的转换,因为正数都是他本身

## 补码转为原码

```
方法一:补码 -1 再取反
-30
补码   10011110
反码   10011101// 在补码的基础上-1
原码   11100010// 把反码取反,得到原码

方法二:对补码再求补码
补码   10011110
反码   11100001// 给补码取反
原码   11100010// 在反码的基础上+1,得到原码
```

不考虑符号位,原码+反码=0xff

```
-10
原码 10001010
补码 11110101
--------------
结果 11111111 =0xff
```

## 公式

```
原码的反码 == 0xff - 原码
补码的反码 == 0xff - 补码
------------------------
原码 = (0xff-补码)+1
0xff-补码 == 补码的反码
原码 = 补码的反码+1 // 对补码再求补码可得原码
```

# 解答

一开始说的为何计算机中有符号类型一旦超过了一定的大小就会变为负数
用 `int8` 类型来说,他的存储大小是 `-2^8~2^7`,能存储的正整数最大是127,一旦+1,那么他的二进制就会超过最大值

```
int8 类型
+ 127
二进制 01111111
// 最高位2^8 是符号位,0表示正数,1表示负数
// 这里一旦超过 127,比如 128
// 10000000 128, 最高位 2^8 是符号位,正整数立即就成为了负整数 -128

负数稍微有点不同
比如 -128 在内存中的补码就是 10000000,他没有原码和反码,因为原码和反码都超过了最大表示范围
但是负整数如果-1也是会变成正整数的最大值
-1 的原码,反码,补码
原码 10000001
反码 11111110 // 原码基础上取反,最高位不变
补码 11111111 // 在反码的基础上+1

然后 -128 -1
10000000 (-128 的补码)
11111111 (-1 的补码)
-------------------
101111111 结果溢出
由于超过了8位,但是我们只保留8位,所以结果是
01111111
```

1729916784 发表于 2023-4-27 01:58

挺不错的

sjtkxy 发表于 2023-6-24 05:00

页: [1]
查看完整版本: 0x01 原码、反码、补码