1. 原码反码补码概念以及转换
1.1 原码 原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值,例如: 原码:[+1]0000 0001 原码:[-1]1000 0001 |
1.2 反码 正数的反码是其本身 负数的反码是在其原码的基础上, 符号位不变,其余各个位取反. 原码:[+1]0000 0001 反码:0000 0001 原码:[-1]1000 0001 反码:1111 1110 |
1.3 补码 正数的补码就是其本身 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1) 原码:[+1]0000 0001 反码:0000 0001 补码:0000 0001 原码:[-1]1000 0001 反码:1111 1110 补码:1111 1111 |
#include <stdio.h>
int main(int argc, const char * argv[]) { // 其实数据存储在内存中都是存储的二进制 // 二进制又可以分为原码、反码、补码 // 其实最终存储在内存中的是补码 // int占4个字节 1个字节8位所以整形就站 32 位 int num = 12; /* // 12的二进制 12在内存中存储的是它的补码 00000000 00000000 00000000 00001100 正数:(三码相同)正数的原码就是它反码,也是它的补码
-12 二进制的最高位我们称之为符号位 如果符号位是0代表是一个正数, 如果符号位是1代表是一个负数
10000000 00000000 00000000 00001100 (-12的原码) 11111111 11111111 11111111 11110011(反码, 符号位不变其它位取反)
11111111 11111111 11111111 11110011 +00000000 00000000 00000000 00000001 _____________________________________________ 11111111 11111111 11111111 11110100(补码 , 反码+1)
结论:无论正数负数在内存中存储的都是补码
11111111 11111111 11111111 11110101 (补码) -00000000 00000000 00000000 00000001 (-1) _____________________________________________ 11111111 11111111 11111111 11110100 (反码) 10000000 00000000 00000000 00001011
*/ printf("%d\n", 0b11111111111111111111111111110101); return 0; } |
2. 为什么要引入反码、补码?
主要是为了方便计算机计算,因为计算机制作加法计算,没有减法计算 1、由于最高为是符号位,如果是0就代表正数,如果是1就代表是负数 2、如果直接存储原码,计算机在计算的时候还需要判断最高位才能计算,效率较低 3、为了方便计算机计算,所以有了反码和补码,有了反码和补码之后,以后计算机就不需要判断最高位,直接计算即可(计算机只做加法计算) 1 + 1 0001 + 0001 ———————— 0010 ==2 1 - 1 == 1 + (-1)==计算机只会做加法 0000 0001 原码 + 1000 0001 原码 ———————————————— 1000 0010 == -2
1 - 1 == 1 + (-1)== 计算机只会做加法 0000 0001 原码(+1反码) + 1111 1110 反码 ———————————————— 1111 1111 == 反码 将计算出来的反码转为原码,再见原码转换为十进制 1000 0000 == 原码 == -0
1 - 1 == 1 + (-1)== 计算机只会做加法 0000 0001 (+1补码) + 1111 1110 (-1补码) —————————————————— 1 0000 0000 == 0 补码 |
最后补充一点 这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128: (-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补 -1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补码就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的) 有人会问 10000000这个补码表示的哪个数的补码呢? 其实这是一个规定,这个数表示的是-128所以n位补码能表示的范围是 -2^(n-1)到2^(n-1)-1 比n位原码能表示的数多一个 |