目录

C学习笔记03进制转换与反码补码原码

【C#学习笔记03】进制转换与反码、补码、原码

1. 进制转换

计算机中的数据通常以二进制形式存储,但在编程和调试过程中,我们经常需要与十进制、八进制和十六进制打交道。因此,掌握进制转换是C语言学习中的重要一环。


1.1 进制的基本概念

  • 二进制(Binary) : 基数为2 ,使用数字0和1。
  • 八进制(Octal) : 基数为8 ,使用数字0到7。
  • 十进制(Decimal) : 基数为10 ,使用数字0到9。
  • 十六进制(Hexadecimal) : 基数为16 ,使用数字0到9和字母A到F。

1.2 进制转换方法

1.2.1 二进制转十进制

将二进制数的每一位乘以 2的幂次方 ,然后相加。

将二进制数​ ​1011​ ​​转换为十进制:

1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 1 * 2^0
= 8 + 0 + 2 + 1
= 11
1.2.2 十进制转二进制

通过 不断除以2并记录余数 ,直到商为0,然后将余数倒序排列。

将十进制数​ ​11​ ​​转换为二进制:

11 / 2 = 5  1
5 / 2 = 2  1
2 / 2 = 1  0
1 / 2 = 0  1

倒序排列余数:​ ​1011​ ​。


1.2.3 二进制转八进制

将二进制数从右到左 每三位一组 ,不足三位补零,然后将每组转换为对应的八进制数。

将二进制数​ ​101110​ ​​转换为八进制:

101 110
5   6

结果为​ ​56​ ​。


1.2.4 二进制转十六进制

将二进制数从右到左 每四位一组 ,不足四位补零,然后将每组转换为对应的十六进制数。

将二进制数​ ​101110​ ​​转换为十六进制:

0010 1110
2    E

结果为​ ​2E​ ​。


1.2.5 十进制转十六进制

通过不断 除以16并记录余数 ,直到商为0,然后将余数倒序排列。

将十进制数​ ​255​ ​转换为十六进制:

255 / 16 = 15  15 (F)
15 / 16 = 0  15 (F)

倒序排列余数:​ ​FF​ ​。


2. 反码、补码和原码

计算机可以区分整数的正负,但是程序最终都会被转换为二进制指令,二进制可以分正负,在二进制数的前面添加1bit,作为符号位,并且bit=0,用于表示二进制数为正数,bit=1,用于表示二进制数为负数。

https://i-blog.csdnimg.cn/img_convert/c3275036853593d4bfacb95f59628f1a.png

可以知道,计算机内部是以二进制的补码方式来存储数据的,所以需要 把二进制数的原码转换为补码 形式。

https://i-blog.csdnimg.cn/img_convert/f7e59749f2d1a73ea1800082380596a8.png

可以知道,正数的原码和补码是相同的,所以 负数才需要把原码转换为补码 ,再进行存储!

https://i-blog.csdnimg.cn/img_convert/6084525693f4dc5e11176e1b1657d09b.png


2.1 原码

原码是二进制数的最基本表示形式,最高位为符号位(0表示正数,1表示负数),其余位表示数值。

  • ​+5​ ​的原码:​ ​00000101​
  • ​-5​ ​的原码:​ ​10000101​

原码表示法存在以下问题:

  • 0有两种表示形式:​ ​00000000​ ​(+0)和​ ​10000000​ ​(-0)。
  • 加减法运算复杂,需要额外的硬件支持。

2.2 反码

反码是对原码的改进,正数的反码与原码相同,负数的反码是对其原码的符号位不变,其余位取反。

  • ​+5​ ​的反码:​ ​00000101​
  • ​-5​ ​的反码:​ ​11111010​

反码表示法仍然存在以下问题:

  • 0有两种表示形式:​ ​00000000​ ​(+0)和​ ​11111111​ ​(-0)。
  • 加减法运算仍然复杂。

2.3 补码

补码是计算机中表示有符号整数的标准方式。正数的补码与原码相同,负数的补码是其反码加1。

  • ​+5​ ​的补码:​ ​00000101​
  • ​-5​ ​的补码:
  • 原码:​ ​10000101​
  • 反码:​ ​11111010​
  • 补码:​ ​11111011​
  • 0只有一种表示形式:​ ​00000000​ ​。
  • 加减法运算统一,可以直接使用加法器实现。

补码的运算

补码的一个重要特性是,一个数的补码的补码等于其原码。因此,补码可以方便地用于表示负数和进行减法运算。

计算​ ​5 - 3​ ​:

  • ​5​ ​的补码:​ ​00000101​
  • ​-3​ ​的补码:​ ​11111101​
  • 相加:​ ​00000101 + 11111101 = 00000010​ ​(结果为​ ​2​ ​)。

注意 : 设计程序时,定义的变量如果是有符号的,则尽量避免写入超过变量范围的数值!!!!!!

字符型: char  1字节 – 有符号 – 数值范围 -128 ~ 127  –  无符号 – 数值范围 0 ~ 255

短整型:short  2字节 – 有符号 – 数值范围 -32768 ~ 32767 无符号 –数值范围 0 ~ 65535


3. C语言中的进制表示与位操作

3.1 进制表示

  • 二进制 :C语言不支持直接表示二进制数,但可以通过前缀​ ​0b​ ​或​ ​0B​ ​表示(某些编译器支持)。
  • 八进制 :以​ ​0​ ​开头,如​ ​012​ ​表示十进制的​ ​10​ ​。
  • 十六进制 :以​ ​0x​ ​或​ ​0X​ ​开头,如​ ​0x1A​ ​表示十进制的​ ​26​ ​。
#include <stdio.h>

int main() {
    int binary = 0b1010;  // 二进制,值为10
    int octal = 012;      // 八进制,值为10
    int hexadecimal = 0x1A;  // 十六进制,值为26
    printf("Binary: %d\n", binary);
    printf("Octal: %d\n", octal);
    printf("Hexadecimal: %d\n", hexadecimal);
    return 0;
}

输出

Binary: 10
Octal: 10
Hexadecimal: 26

3.2 位操作

C语言提供了以下位操作运算符:

  • 按位与(​ & ​ :对应位都为1时结果为1,否则为0。
  • 按位或(​ | ​ :对应位有一个为1时结果为1,否则为0。
  • 按位异或(​ ^ ​ :对应位不同时结果为1,否则为0。
  • 按位取反(​ ~ ​ :将所有位取反。
  • 左移(​ << ​ :将二进制数向左移动指定位数,低位补0。
  • 右移( ​ `​
    ​` ​ :将二进制数向右移动指定位数,高位补符号位(算术右移)或0(逻辑右移)。
#include <stdio.h>

int main() {
    int a = 5;  // 二进制:00000101
    int b = 3;  // 二进制:00000011

    printf("a & b: %d\n", a & b);  // 00000001 (1)
    printf("a | b: %d\n", a | b);  // 00000111 (7)
    printf("a ^ b: %d\n", a ^ b);  // 00000110 (6)
    printf("~a: %d\n", ~a);        // 11111010 (-6,补码表示)
    printf("a << 1: %d\n", a << 1);  // 00001010 (10)
    printf("a >> 1: %d\n", a >> 1);  // 00000010 (2)
    return 0;
}

输出

a & b: 1
a | b: 7
a ^ b: 6
~a: -6
a << 1: 10
a >> 1: 2