初识C语言之原码、反码、补码的理解

文章目录

  • 前言
  • 一、原码、反码、补码的概念
  • 二、原码、反码、补码的计算
    • 1.原码
    • 2.反码
    • 3.补码
  • 总结


前言

本文为C语言初学者对原码、反码、补码的学习笔记。理解略浅。


一、原码、反码、补码的概念

原码就是符号位加上真值的绝对值,最高位为符号位,其余为表示值。正数的原码反码补码都是其本身,你可认为正数原码就是反码或者补码。负数的补码符号位不变,其余按位取反。补码等于反码加1,原码符号位不变其余按位取反后加1为反码。

二、原码、反码、补码的计算

1.原码

原码就是符号位加上真值的绝对值,用最高位(第一位)表示符号位,其余表示值,示例:如果是8位二进制:
[+1] = [00000001]
[-1] = [10000001]
第一位是符号位,因为第一位是符号位,所以8位二进制的取值范围是:
[+1]的取值范围为:[01111111] 即 [+127]
[-1] 的取值范围为:[11111111] 即 [ -127]

2.反码

正数的反码是其本身,你可以认为它即是原码又是反码。负数的反码是在其原码的基础上符号位不变,其余位按位取反。示例:如果是8位二进制:
[+1] = 原码: [00000001] = 反码: [00000001]
[-1] = 原码: [10000001] = 反码: [11111110]

3.补码

正数的补码就是其本身,你即可以认为它就是补码又可以认为是原码或反码,负数的补码就是,在其原码的基础上,符号位不变,其余按位取反后 +1。示例:如果是8位二进制
[+1] = 原码: [00000001] = 反码: [00000001] = 补码: [00000001]
[-1] = 原码: [10000001] = 反码: [11111110] = 补码: [11111111]
而计算机在内存中存储方式就是补码


总结

既然有了原码为什么还要用反码和补码?
人可以一知道第一位是符号位,在计算机的时候我们会根据符号位对真值区域的加减,但是对于计算机加减乘除已经是最基本运算,计算机考虑符号位显然让计算机基本电路设计会变得十分复杂。于是人们想出了符号位也加入运算,根据运算法则减去一个正数等于加上一个负数,如:1 - 1 = 1 + (-1) = 0; 所以计算机只有加法没有减法。这让计算机的运算更简单。
所以符号位也加入运算的话用原码反码补码的实现是这样的:
原码:
1 + (-1) = 原码[00000001] + 原码[10000001] = [10000010] = -2
显然这样算出来是不正确的。这就是为何计算机内部不使用原码表示一个数。
为了解决原码做减法的问题出现了反码,反码实现是这样的:
反码:
1 + (-1) = 反码[00000001] + 反码[11111110] = 反码[11111111] = 原码[10000000] = -0
这样计算真值不是正确的,唯一的问题就出现在 0 的时候,虽然都知道 -0和+0 都是 0,但是带符号是没有任何意义的,而且会有 [00000000] (原码) 和 [10000000] (原码) 两个编码表示 0。于是补码出现,解决了0的符号和两个编码问题。
补码:
1 + (-1) = 补码[00000001] + 补码[11111111] = 补码[00000000] = 原码[00000000] = 0
1 + (-2) = 补码[00000001] + 补码[11111101] = 补码[11111110] = 原码[10000001] = -1
0 = [00000000]这样之前的-0就被解决了,而且可以用[10000000]可以表示-128
-1 + (-127) = 原码[10000001] + 原码[11111111] = 补码[11111111] + 补码[10000001] = 补码[10000000] = -128
但是实际上-128用的是原来的-0,所以-128没有原码和反码表示,-128 补码[10000000]算出来的原码是[00000000]。很明显这是不正确的。
使用补码不仅解决 -0 和两个编码的问题,而且能多表示一个最低数,这就是为什么8位二进制的原码和反码表示的范围 [-127, 127]。而补码表示的范围 [-128, 127]

你可能感兴趣的:(C/C++,c语言,c++)