数的机器码表示(原码 反码 补码 移码)

首先区分两个概念:真值机器码

  • 真值:一般书写的数
  • 机器码:机器中表示的数

为了解决在计算机内部数的正、负符号和小数点运算问题,而产生了把符号位和数值位一起编码来表示相应的数的表示方法,如原码,反码,补码,移码

1.原码
  • 表示方法:符号位 + 二进制数的绝对值
  • 符号位:0为正,1为负,有+0-0之分
正数:0+二进制数
负数:1+二进制数
  • 特点:表示简单,易于同真值之间进行转换,实现乘除运算规则简单。但进行减运算十分麻烦
  • 例子:3的二进制数是11,则+3的原码是011,-3的原码是111
  • 使用原码做减法( 11=0 1 − 1 = 0 )
    11=1+(1)=[00000001]+[10000001]=[10000010]=2 1 − 1 = 1 + ( − 1 ) = [ 00000001 ] 原 + [ 10000001 ] 原 = [ 10000010 ] 原 = − 2
    结果错误
2.反码
  • 表示方法:正数的表示与原、补码相同. 负数的反码符号位为1,数值位是将原码的数值按位取反,就得到该数的反码表示。
  • 符号位:0为正,1为负,有+0-0之分
正数:0+二进制数
负数:1+二进制数按位取反
  • 特点:为求补码提供便利
  • 例子:3的二进制数是11,则+3的反码是011,-3的反码是100
  • 使用反码做减法( 11=0 1 − 1 = 0 )
    11=1+(1)=[00000001]+[10000001]=[00000001]+[11111110]=[11111111]=[10000000]=0 1 − 1 = 1 + ( − 1 ) = [ 0000 0001 ] 原 + [ 1000 0001 ] 原 = [ 0000 0001 ] 反 + [ 1111 1110 ] 反 = [ 1111 1111 ] 反 = [ 1000 0000 ] 原 = − 0
    结果正确,但出现了-0,这里的-0和+0是没有区别的,所以在这里让0带符号是没有意义的(数学上有时候需要带符号的0,但这里确实不需要,而且会使得对于同一个数有两种编码方式)
3.补码
  • 表示方法:正数的补码符号位为0 ,尾数与原码相同. 负数的补码符号位为1,数值位是将原码的数值按位取反,再在末位加1
  • 符号位:0为正,1为负,无+0-0之分
正数:0+二进制数
负数:1+(二进制数按位取反,末位+1)
  • 特点:将减法转化为加法
  • 例子:3的二进制数是11,则+3的补码是011,-3的补码是101
  • 使用补码做减法
    • 11=0 1 − 1 = 0
      11=1+(1)=[00000001]+[10000001]=[00000001]+[11111111]=[00000000]=[00000000] 1 − 1 = 1 + ( − 1 ) = [ 0000 0001 ] 原 + [ 1000 0001 ] 原 = [ 0000 0001 ] 补 + [ 1111 1111 ] 补 = [ 0000 0000 ] 补 = [ 0000 0000 ] 原
      结果正确,且没有出现-0,这里是正负相加的结果,那如果是通过正正相加或者负负相加得到 [10000000] [ 1000 0000 ] 补 ,又意味着什么呢?
    • 正正相加:( 271)+1=128 2 7 − 1 ) + 1 = 128 正溢
      (271)+1==[01111111]+[00000001]=[01111111]+[00000001]=[10000000]=[10000000] ( 2 7 − 1 ) + 1 == [ 0111 1111 ] 原 + [ 0000 0001 ] 原 = [ 0111 1111 ] 补 + [ 0000 0001 ] 补 = [ 1000 0000 ] 补 = [ 1000 0000 ] 原
      这里可以看到,用补码时, [10000000] [ 1000 0000 ] 原 表示上溢的结果
    • 负负相加: 26+(26)=128 − 2 6 + ( − 2 6 ) = − 128 负溢
      26+(26)==[11000000]+[11000000]=[11000000]+[11000000]=[10000000]=[10000000] − 2 6 + ( − 2 6 ) == [ 11000000 ] 原 + [ 11000000 ] 原 = [ 11000000 ] 补 + [ 11000000 ] 补 = [ 1000 0000 ] 补 = [ 1000 0000 ] 原
      这里可以看到,用补码时, [10000000] [ 1000 0000 ] 原 也可以表示下溢的结果

在定点整数机器中,数的表示范围为 |x|<(2n1) | x | < ( 2 n − 1 ) ,但n位二进制补码数的表示范围是 2n1 − 2 n − 1 2n11 2 n − 1 − 1 ,
其中用 [10000000] [ 1000 0000 ] 原 来表示 2n1 − 2 n − 1 ,这样不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].
但是,同时要注意,用补码表示的 2n1 − 2 n − 1 是没有对应的反码和原码的,因为实际上是使用以前的-0的补码来表示-128

4.移码
  • 表示方法:移码和补码尾数相同,符号位相反
  • 符号位:1为正,0为负(注意,移码的符号表示与其他三种都不一样)
正数:1+二进制数
负数:0+(二进制数按位取反,末位+1)
  • 特点:通常用于表示浮点数的阶码
  • 例子:3的二进制数是11,则+3的移码是111,-3的移码是001

比较

表示方法正数负数+1011111-1011111
原码0+二进制数1+二进制数0101111111011111
反码0+二进制数1+二进制数按位取反0101111110100000
补码0+二进制数1+(二进制数按位取反,末位+1)0101111110100001
移码1+二进制数0+(二进制数按位取反,末位+1)1101111100100001
  • 14
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
定点整的机器表示: ```java public class FixedPointNumber { private int bits; // 总位 private int integerBits; // 整 private int fractionBits; // 小 private int value; // 值 public FixedPointNumber(int bits, int integerBits, int fractionBits, int value) { this.bits = bits; this.integerBits = integerBits; this.fractionBits = fractionBits; this.value = value; } public int getBits() { return bits; } public int getIntegerBits() { return integerBits; } public int getFractionBits() { return fractionBits; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } // 将整转为定点 public static FixedPointNumber fromInteger(int integer, int integerBits, int fractionBits) { int value = integer << fractionBits; return new FixedPointNumber(integerBits + fractionBits, integerBits, fractionBits, value); } // 将小转为定点 public static FixedPointNumber fromFloat(float floatValue, int integerBits, int fractionBits) { int value = (int) (floatValue * (1 << fractionBits)); return new FixedPointNumber(integerBits + fractionBits, integerBits, fractionBits, value); } // 将定点转为浮点 public float toFloat() { return ((float) value) / (1 << fractionBits); } // 将定点转为整 public int toInteger() { return value >> fractionBits; } // 将定点转为字符串 public String toString() { StringBuilder sb = new StringBuilder(); int mask = 1 << (bits - 1); for (int i = 0; i < bits; i++) { if ((value & (mask >> i)) != 0) { sb.append("1"); } else { sb.append("0"); } if (i == integerBits - 1) { sb.append("."); } } return sb.toString(); } } ``` 定点整的变形补码加减运算: ```java public class FixedPointArithmetic { private int bits; // 总位 private int integerBits; // 整 private int fractionBits; // 小 private int mask; // 位掩码 public FixedPointArithmetic(int bits, int integerBits, int fractionBits) { this.bits = bits; this.integerBits = integerBits; this.fractionBits = fractionBits; this.mask = (1 << bits) - 1; } // 定点变形补码加法 public FixedPointNumber add(FixedPointNumber a, FixedPointNumber b) { int sum = (a.getValue() & mask) + (b.getValue() & mask); if (sum >= (1 << bits)) { sum -= (1 << bits); } return new FixedPointNumber(bits, integerBits, fractionBits, sum); } // 定点变形补码减法 public FixedPointNumber sub(FixedPointNumber a, FixedPointNumber b) { int diff = (a.getValue() & mask) - (b.getValue() & mask); if (diff < 0) { diff += (1 << bits); } return new FixedPointNumber(bits, integerBits, fractionBits, diff); } // 定点整原码一位乘法运算 public FixedPointNumber mul(FixedPointNumber a, FixedPointNumber b) { int product = (a.getValue() * b.getValue()) >> b.getFractionBits(); return new FixedPointNumber(bits, integerBits, fractionBits, product); } } ``` 浮点的加减运算: ```java public class FloatArithmetic { private int bits; // 总位 private int exponentBits; // 指 private int fractionBits; // 小 private int bias; // 偏移量 public FloatArithmetic(int bits, int exponentBits, int fractionBits, int bias) { this.bits = bits; this.exponentBits = exponentBits; this.fractionBits = fractionBits; this.bias = bias; } // 浮点加法 public float add(float a, float b) { // 将 a 和 b 转换为 IEEE 754 浮点 int aBits = Float.floatToIntBits(a); int bBits = Float.floatToIntBits(b); // 提取符号位、指位和尾位 int aSign = (aBits >> 31) & 0x1; int aExponent = (aBits >> 23) & 0xff; int aFraction = aBits & 0x7fffff; int bSign = (bBits >> 31) & 0x1; int bExponent = (bBits >> 23) & 0xff; int bFraction = bBits & 0x7fffff; // 对阶 int shift = Math.abs(aExponent - bExponent); if (aExponent > bExponent) { bFraction |= 0x800000; bFraction >>= shift; bExponent = aExponent; } else { aFraction |= 0x800000; aFraction >>= shift; aExponent = bExponent; } // 溢出检查 if (aExponent == 0xff || bExponent == 0xff) { return Float.NaN; } // 计算和的符号位、指位和尾位 int sumSign, sumExponent, sumFraction; if (aSign == bSign) { sumSign = aSign; sumExponent = aExponent; sumFraction = aFraction + bFraction; if (sumFraction >= 0x800000) { sumFraction >>= 1; sumExponent++; } } else { if (aFraction == bFraction) { return 0.0f; } if (aFraction > bFraction) { sumSign = aSign; sumExponent = aExponent; sumFraction = aFraction - bFraction; } else { sumSign = bSign; sumExponent = bExponent; sumFraction = bFraction - aFraction; } while ((sumFraction & 0x800000) == 0) { sumFraction <<= 1; sumExponent--; } } // 将和转换为浮点 int sumBits = (sumSign << 31) | (sumExponent << 23) | (sumFraction & 0x7fffff); return Float.intBitsToFloat(sumBits); } // 浮点减法 public float sub(float a, float b) { // 将 b 取反后加上 a int bBits = Float.floatToIntBits(b); bBits ^= 0x80000000; return add(a, Float.intBitsToFloat(bBits)); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值