原码,反码,补码,移码以及转换方式(附C语言实现代码)

常见的编码及其概述:

  • 原码(Sign-Magnitude)

    • 用最高位(符号位)表示数值的正负,剩余位表示数值的大小。
    • 最高位为0:正数;最高位为1:负数。
    • 优点:简单直观。
    • 缺点:存在“正零”和“负零”。
  • 反码(Ones' Complement)

    • 正数的表示与原码相同。
    • 负数的表示:符号位为1,数值位按原码逐位取反。
    • 缺点:同样存在“正零”和“负零”,且计算复杂。
  • 补码(Two's Complement)

    • 正数的表示与原码相同。
    • 负数的表示:符号位为1,数值位为原码的反码+1。
    • 优点:计算简单,负数的表示唯一。
    • 常用于计算机系统中。
  • 移码(Excess-K Code)

    • 一种无符号编码。
    • 通过对原码整体加一个偏移量 KK(如127、1023)表示数值。
    • 常用于浮点数表示中的指数部分。

码之间的转换

  • 原码与反码之间的转换:

  • 正数:原码和反码相同。
  • 负数:反码 = 原码逐位取反(符号位除外)。
  • //正数:原码和反码相同。
    //负数:反码 = 原码逐位取反(符号位除外)
    int toOnesComplement(int num) {
        if (num >= 0) {
            return num; // 正数原码和反码相同
        }
        return ~(-num); // 负数原码转反码
    }
    
    int fromOnesComplement(int num) {
        if ((num & 0x8000) == 0) {
            return num; // 反码为正数时不变
        }
        return -(~num); // 反码为负数时取反
    }
    

  • 原码与补码之间的转换:

  • 正数:原码和补码相同。
  • 负数:补码 = 原码的反码 + 1。
  • int toTwosComplement(int num) {
        if (num >= 0) {
            return num; // 正数原码和补码相同
        }
        return (~(-num) + 1); // 负数原码转补码
    }
    
    int fromTwosComplement(int num) {
        if ((num & 0x8000) == 0) {
            return num; // 补码为正数时不变
        }
        return -(~(num - 1)); // 补码为负数时转原码
    }
    
  • 原码与移码之间的转换:

  • 移码 = 原码 + 偏移量 K。
  • K通常为 ,其中 n为位数
  • int toExcessK(int num, int K) {
        return num + K;
    }
    
    int fromExcessK(int code, int K) {
        return code - K;
    }
    
  • 反码与补码之间的转换:

  • 正数:反码和补码相同。
  • 负数:补码 = 反码 + 1。
  • int onesToTwosComplement(int num) {
        if ((num & 0x8000) == 0) {
            return num; // 正数反码和补码相同
        }
        return num + 1; // 负数反码转补码
    }
    
    int twosToOnesComplement(int num) {
        if ((num & 0x8000) == 0) {
            return num; // 正数补码和反码相同
        }
        return num - 1; // 负数补码转反码
    }
    


完整代码示例

#include <stdio.h>

// 原码 -> 反码
int toOnesComplement(int num) {
    if (num >= 0) {
        return num; // 正数原码和反码相同
    }
    return ~(-num); // 负数原码转反码
}

// 反码 -> 原码
int fromOnesComplement(int num) {
    if ((num & 0x8000) == 0) {
        return num; // 反码为正数时不变
    }
    return -(~num); // 反码为负数时取反
}

// 原码 -> 补码
int toTwosComplement(int num) {
    if (num >= 0) {
        return num; // 正数原码和补码相同
    }
    return (~(-num) + 1); // 负数原码转补码
}

// 补码 -> 原码
int fromTwosComplement(int num) {
    if ((num & 0x8000) == 0) {
        return num; // 补码为正数时不变
    }
    return -(~(num - 1)); // 补码为负数时转原码
}

// 原码 -> 移码
int toExcessK(int num, int K) {
    return num + K;
}

// 移码 -> 原码
int fromExcessK(int code, int K) {
    return code - K;
}

int main() {
    int num = -5; // 示例数字

    // 原码与反码
    int ones = toOnesComplement(num);
    printf("原码 -> 反码: %d\n", ones);
    printf("反码 -> 原码: %d\n", fromOnesComplement(ones));

    // 原码与补码
    int twos = toTwosComplement(num);
    printf("原码 -> 补码: %d\n", twos);
    printf("补码 -> 原码: %d\n", fromTwosComplement(twos));

    // 原码与移码 (K = 127)
    int excessK = toExcessK(num, 127);
    printf("原码 -> 移码: %d\n", excessK);
    printf("移码 -> 原码: %d\n", fromExcessK(excessK, 127));

    return 0;
}

总结

  • 原码直观但有冗余(正零和负零)。
  • 反码适合简化取反计算。
  • 补码是计算机中最常用的数值表示,解决了原码和反码的问题。
  • 移码主要用于特定场景(如浮点数表示)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Flocx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值