草庐IT

原码反码补码

小橘灯 2023-03-28 原文

3 原码、反码、补码

3.1 知识点补充

在计算机内部,所有信息都是用二进制数串的形式表示的。整数通常都有正负之分,计算机中的整数分为无符号的和带符号的。无符号的整数用来表示0和正整数,即自然数;带符号的正数可以表示所有的整数。

由于计算机中符号和数字一样,都必须用二进制数串来表示,因此,正负号也必须用0、1来表示。通常我们用最高的有效位来 表示数的符号(当用8位来表示一个整数时,第8位即为最高有效位,当用16位来表示一个整数时,第16位即为最高有效位。)0表示正号、1表示负号。

这种正负号数字化(0表示正号、1表示负号)的机内表示形式就称为机器码或者机器数,而相应的机器外部用正负号表示的数称为真值。将一个真值表示成二进制字串的机器数的过程就称为编码

无符号数没有原码、反码和补码一说。只有带符号数才存在不同的编码方式。带符号整数有原码、反码、补码等几种编码方式。

**原码即直接将真值转换为其相应的二进制形式,而反码和补码是对原码进行某种转换编码方式。**正整数的原 码、反码和补码都一样,负数的反码是对原码的除符号位外的其他位进行取反后的结果(取反即如果该位为0则变为1,而该位为1则变为0的操作)。而补码是先求原码的反码,然后在反码的末尾位加1 后得到的结果,即补码是反码+1。IBM-PC中带符号整数都采用补码形式表示。

注意,只是带符号的整数采用补码存储表示的,浮点数另有其存储方式。

  1. 正数的补码是其本身
  2. 负数的反码,符号位不变,其余的按位取反
  3. 负数的补码,反码加1

对于字长为8位有符号的int,因为最高为符号位,占1位,所以最小为(1111111)2 = (-127)10,最大为(0111111)2 = (127)10;即其原码范围为:-127~127

有符号的8位二进制的原值表达范围为:-127至127,此时共255个数字;然而,8位二进制 的补码排列共有$A_{2}^{8}$ = 256个,0000 0000 至1111 1111 。

补码组合 范围 个数
0000 0000 - 0111 1111 0 ~+127 128
10000000 多余的一种组合待定 1
1000 0001 - 1111 1111 -1~-127 127

**10000000 **看似要被浪费掉了啊!其实不然,( 100000000 ) 2 = ( 2^7 ) 10 = ( 128 ) 10,这个组合要利用起来,不能太偏离数值意义,表示128,显得更直观。

**从大到小,依次减1看一下规律:**
十进制 (字长8bit) 原码 反码 补码
127 0111 1111 0111 1111 0111 1111
126 0111 1110 0111 1110 0111 1110
…… …… …… ……
10 0000 1010 0000 1010 0000 1010
…… …… …… ……
2 0000 0010 0000 0010 0000 0010
1 0000 0001 0000 0001 0000 0001
+0 0000 0000 0000 0000 0000 0000
-1 1000 0001 1111 1110 1111 1111
-2 1000 0010 1111 1101 1111 1110
…… …… …… ……
-10 10001010 11110101 11110110
…… …… …… ……
-127 11111111 10000000 10000001
待定 10000000 10000000 10000000

从递减规律中,发现,**10000000 **表示-128更合适。

即规定:-128的补码为 10000000

求10 -10 0 -128 127 的原码、反码、补码

十进制 (字长8bit) 原码 反码 补码
10 00001010 00001010 00001010
-10 10001010 11110101 11110110
-1 1000 0001 1111 1110 1111 1111
+0 00000000 00000000 00000000
-0 10000000 11111111 00000000
-128 10000000
127 01111111 01111111 01111111
-127 11111111 10000000 10000001

+0和-0的补码是一样的。即 0的补码只有一种表示,0的补码是0000 0000,

# 四 输出结果,解释为什么是这样的
char c = 128;
printf("%d\n",c);
printf("%hhd\n",c);
printf("%hd\n",c);
printf("%hu\n",c);

4.1 格式输出符

格式符号 意义
%a 浮点数、十六进制数字和p-记数法 (C99)
%A 浮点数、十六进制数字和P-记数法 (C99)
%c 一个字符
%d 有符号十进制整数
%e 浮点数、e-记数法
%E 浮点数、E-记数法
%f 浮点数,十进制记数法
%g 根据数值不同自动选择%f或者%e。%e格式在指数小于-4或者大于等于精度时使用
%G 根据数值不同自动选择%f或者%E。%E格式在指数小于-4或者大于等于精度时使用
%i 有符号十进制整数 (与%d相同)
%o 无符号八进制整数
%p 指针(就是指地址)
%s 字符串
%u 无符号十进制整数
%x 使用十六进制数字0f 的无符号十六进制整数
%X 使用十六进制数字0F的无符号十六进制整数
%% 打印一个百分号
## 4.2 格式输出其修饰符
修饰符 意义 示例
h 和整数转换说明符一起使用,表示一个short int 或者 unsigned short int 类型数值。 "%hd
hh 和整数转换说明符一起使用,表示一个signed char 或者unsigned char类型数值。 "%hhd"
j 和整数转换说明符一起使用,表示一个intmax_t或uintmax_t值。 "%jd"
l 和整数说明符一起使用,表示一个long int 或者unsigned long int 类型值。 "%8lu"
ll 和整数说明符一起使用,表示一个long long int或 unsigned long long int 类型值 (C99)。 "%lld"
L 和浮点转换说明符一起使用,表示一个long double值。 "%8.4Le"
t 和整数转换说明符一起使用,表示一个ptrdiff_t值(与两个指针之间的差相对应的类型) (C99) "%td"
- 项目是左对齐的,也就是说,会把项目打印在字段的左侧开始处 "%-20s"
+ 有符号的值若为正,则显示带加号的符号;若为负,则带减号的符号。 "%+3.2"
(空格) 有符号的值若为正,则显示时带前导空格(但是不显示符号);若为负,则带减号符号。+标志会覆盖空格标志。 "% 3.2"
# 使用转换说明的可选形式。若为%o格式,则以0开始;若为%x和%X格式,则以0x或0X开始,对于所有的浮点形式,#保证了即使不限任何数字,也打印一个小数点字符。对于%g和%G格式,它防止尾随零被删除。 "%#o"
0 对于所有的数字格式,用前导零而不是用空格填充字段宽度。如果出现-标志或者指定了精度(对于整数)则忽略该标志。 "%010d"
## 4.3 机器码求解
char c = 128;

此处是将一个int赋值给一个char类型变量,进行隐式类型转换.int型数值赋给char型变量时,只保留其最低8位,高位部分舍弃。

首先,整型128在一个字长为4个字节的的原码为00000000 00000000 00000000 10000000,当把一个int类型赋值给一个有符号的char类型时,高位被舍弃。实际给c的是10000000,此时,被系统认为是一个负数,补码为10000000,结合上面的分析,其值就是**-128**。

4.4 格式化输出

char c = 128;

4.4.1 结论

先给出通过这次作业得出的一个不完全归纳法结论吧,也是我做出的解释。最后会给出原码验证

1、正数的原码的反码、补码是其本身,扩展时,高位补0;

2、负数扩展为有符号的高位补1,无符号的高位补0。

2、负数扩展时,高位补 1。格式化输出无符号的数据时,机器码即为原码;格式化输出有符号数据时,要先求其原码,然后求得真值。

c 的机器码为10000000

4.4.2 输出32位有符号int:

printf("%d\n",c);//默认的 int ,32位

1000 0000 转为有符号的32位机器码:1111 1111 1111 1111 1111 1111 1000 0000

反码:1111 1111 1111 1111 1111 1111 0111 1111

原码:1000 0000 0000 0000 0000 0000 1000 0000

有符号,其值为:-128.

4.4.3 输出8位有符号signed char:

printf("%hhd\n",c);//signed char,  8位

8位机器码:1000 0000

此机器码没有反码和源码,机器码即为真值:-128.

4.4.4 输出16位有符号 short int

printf("%hd\n",c);//short int,16 位

1000 0000 转为有符号的16位机器码:1111 1111 1000 0000

反码:1111 1111 0111 1111 原码:1000 0000 1000 0000

有符号,其值为:-128.

4.4.5 输出16位无符号 short int

printf("%hu\n",c);

1000 0000 转为16位机器码:1111 1111 1000 0000

格式化输出无符号十进制数据,此码即为原码。

原码:1111 1111 1000 0000

做无符号运算,其值:65408

4.5 源码

#include <iostream>
#include <bitset>

int main() {
    using namespace std;
    cout << "Hello Biter !" << endl;
    char c = 128;
    cout << "---------------- -" << int(c) << "-----------------------  " << endl;
    cout << "char 型 机器码 =  " << bitset<sizeof(char) * 8>(c) << endl;
    cout << "int 型 机器码 =  " << bitset<sizeof(int) * 8>(c) << endl;
    cout << "signed char 型 机器码 =  " << bitset<sizeof(signed char) * 8>(c) << endl;
    cout << "short int 型 机器码 =  " << bitset<sizeof(short int) * 8>(c) << endl;
    cout << "unsigned short int 型 机器码 =  " << bitset<sizeof(unsigned short int) * 8>(c) << endl;
    cout << "char 二进制形式为 =  " << bitset<sizeof(char) * 8>(c) << endl;
    cout << "--------------------------------------------  " << endl;
//    printf("将 char 直接 输出 128 超范围了 = %c\n", c);
//    cout << "--------------------------------------------  " << endl;
    printf("有符号的 int 输出 = %d\n", c);
    cout << "--------------------------------------------  " << endl;
    printf("有符号的 signed char 输出 = %hhd\n", c);//1000,0000
    cout << "--------------------------------------------  " << endl;
    printf("有符号的 short int 输出= %hd\n", c);//0000,0000 1000,0000
    cout << "--------------------------------------------  " << endl;
    printf("无符号的 unsigned short int 输出= %hu\n", c);// 1111,1111 1000,0000
    cout << "--------------------------------------------  " << endl;

    return 0;
}

有关原码反码补码的更多相关文章

  1. java - 了解使用二进制补码写入 bluej 的程序。 - 2

    我刚开始使用Bluej来了解有关计算机如何存储整数的更多信息。我有一个放入Bluej中的小程序,它将名为x的整数的值设置为MAX_VALUE-3,然后将1加到x六次,每次打印出一个新值。一个添加是不正确的,尽管我需要帮助来理解我收到的哪个值不正确以及为什么我得到的结果是“奇怪的”。请记住,我对计算机语言非常天真,我只是在读一本关于存储整数的书。我的书是J.GlennBrookshear的《计算机科学》第11版。这是我放入BlueJ的程序:publicclassAdd{publicAdd(){inti,x;x=java.lang.Integer.MAX_VALUE-3;i=0;while

  2. c# - 补码转换 - 2

    我需要将二进制补码格式的字节转换为正整数字节。范围-128到127映射到0到255。Examples:-128(10000000)->0,127(01111111)->255,etc.EDIT为了消除混淆,输入字节(当然)是0到255范围内的无符号整数。但是它使用二进制表示-128到127范围内的有符号整数补充格式。比如输入的字节值128(二进制10000000)实际代表的是-128。额外编辑好的,假设我们有以下字节流0,255,254,1,127。在二进制补码格式中,这表示0、-1、-2、1、127。我需要将其限制在0到255的范围内。有关更多信息,请查看这篇很难找到的文章:Two'

  3. c# - 确定 .NET 中两个 IEnumerable<T> 集的相对补码 - 2

    有没有简单的方法来获取relativecomplement两套?也许使用LINQ?我必须找到集合A相对于B的相对恭维。A和B的类型都是HashSet但我认为该算法可以更通用(IEnumerable甚至ISet)?我可以使用VB.NET或C#中的解决方案。 最佳答案 你试过了吗Enumerable.Except?setB.Except(setA)例子:HashSetsetB=newHashSet{1,2,3,4,5};HashSetsetA=newHashSet{1,3,5,7};HashSetresult=newHashSet(se

  4. Javascript波浪号和二的补码 - 2

    Two'scomplementmethod-生成-(x+1)。例如,当JavaScript遇到波浪号时,他使用这种方法:~5=-(5+1)=-6.好-让我们更深入。现在让我们谈谈二进制补码方法。5=00000101Flip=11111010addone=11111011所以11111011是-5。如何?再次:翻转:00000100加一个:00000101所以它是-5。那么~5=-6如何解决?这个-6来自哪里? 最佳答案 首先你要明白~是按位翻转运算符,它和取反运算符-是不一样的。~只进行按位翻转,但取反运算符-进行按位翻转并加一(对

  5. javascript - 将带符号的十进制转换为用二进制补码编码的十六进制 - 2

    我需要使用二进制补码符号将一个有符号整数编码为十六进制。例如我想转换e.g.-24375to0xffffa0c9.到目前为止,我一直在研究以下几行:parseInt(-24375).toString(2)>"-101111100110111"这与WolframAlphadisplays相匹配,但我不确定如何获得数字(ffffa0c9)的带符号24位int表示。我已经弄清楚如何获取无符号二进制数并将其表示为二进制补码:~parseInt("101111100110111",2)+1>-23475但我不确定要将此数字的二进制表示转换为十六进制。有什么想法吗? 最

  6. 山东大学计算机组成与设计实验六 二进制补码加法器实验 - 2

    山东大学计算机组成与设计实验六二进制补码加法器实验,山东大学计算机组成与设计实验,山东大学计算机组成与设计实验报告,计算机组成原理实验报告,山东大学计算机组成原理实验报告文章目录实验6二进制补码加法器实验一、实验目的:二、实验方案:三、实验要求:(1)原理图:(2)管脚锁定:实验结果:加法:减法:实验6二进制补码加法器实验一、实验目的:根据补码加法器的模型,理解数据流及其时序关系。掌握加法器实现补码加、减运算的基本原理。二、实验方案:本实验运算器模型,可分为数据运算以及符号位的产生两部分。三、实验要求:◆数据宽度为4位,设计出实验线路图。◆设计试验步骤。◆使用开关进行数据加载,完成补码加、减运

  7. java - 如何将负整数转换为二进制补码形式? ( java ) - 2

    我需要将正数和负数转换为二进制格式-例如,2转换为“00000010”,-2转换为“11111110”。我不需要超过12位左右,所以如果字符串长于12位,我可以去掉前导符号位。看起来Integer.toBinaryString()会计算正数,但有没有可以计算负数的? 最佳答案 Integer.toBinaryString也适用于负数。:-)例如,Integer.toBinaryString(-2)返回11111111111111111111111111111110。如果您取最右边的12个字符,则根据需要您有低12位。

  8. c++ - 计算机总是按照2的补码法来表示负数吗? - 2

    这个问题在这里已经有了答案:Signmagnitude,One'scomplement,Two'sComplement(1个回答)Arethereanynon-twos-complementimplementationsofC?(2个答案)Whynotenforce2'scomplementinC++?(4个答案)Isone'scomplementareal-worldissue,orjustahistoricalone?(9个回答)SignedMagnitudeand1'sComplement(1个回答)关闭5年前。请查看以下代码并帮助我理解它inta=1;intb=~1;print

  9. c++ - 如何计算给定 vector 索引的补码? - 2

    我有一个3D点vector,由类Point3D表示,std::vectorpoints;我还有一个size_t包含points索引的vectorvector,std::vectorindices_true;现在我想构建indices_true的逆函数,即我想建立另一个索引vectorindices_false包含indices_true中缺失的所有索引.如何以比以下方式更快的方式完成此操作:for(size_ti=0;i 最佳答案 需要额外的内存,但会产生线性算法:这是一个尝试(既没有编译也没有测试):indices_false.r

  10. c++ - 校验和计算——所有字节的补码和 - 2

    我有关于创建这样描述的消息的校验和的说明:校验和由一个字节组成,等于从“消息类型”字开始到消息block结尾的所有字节的二进制补码和(不包括传输的校验和)。忽略最高有效位的进位。我找到的另一个描述是:校验和值包含数据消息中其他字(即消息类型、消息长度和数据字)的模256和的二进制补码。接收设备可以计算接收到的字的模256和,并将该和添加到接收到的校验和字中。结果为零通常表示消息已正确接收。我理解这意味着我将消息中所有字节的值相加(不包括校验和),得到这个数字的模256。得到这个数字的补码,这就是我的校验和。但是我在处理示例消息示例时遇到了问题(来自设计文档,因此我必须假设它已被正确编码

随机推荐