重要:原码、反码、补码...

涉及计算机运算中的底层运算,所以一步步来。

一、pascal中的整数类型

Type           Range                                                 Size in bytes
Byte           0 .. 255                                              1
Shortint       -128 .. 127                                           1
Word           0 .. 65535                                            2
Integer        -32768 .. 32767                                       2
Longword       0 .. 4294967295                                       4
Longint        -2147483648 .. 2147483647                             4
QWord          0 .. 18446744073709551615                             8
Int64          -9223372036854775808 .. 9223372036854775807           8
 
整数有占1、2、4、8字节的,分为无符号与有符号。有符号的整数比无符号的常用。
有符号的整数与内存的约定是补码的形式。数据在内存中以补码形式存储,运算也以补码形式运算,运算结果也是补码。
int64与qword不是顺序类型,不能作为循环控制变量。
word经常被翻译成“字”,是占两个字节的无符号整数类型。
Dword是longword的别名,意思是double word,两个字是4字节。
Qword是四个字。带word的都是些无符号整数

运行以下程序,加深印象:

program test;
begin
  writeln(sizeof(byte));     //1
  writeln(sizeof(shortint)); //1
  writeln(sizeof(word));     //2
  writeln(sizeof(integer));  //2
  writeln(sizeof(longword)); //4
  writeln(sizeof(longint));  //4
  writeln(sizeof(qword));    //8
  writeln(sizeof(int64));    //8
  writeln(MaxLongint); //取得longint的最大整数值
end.
View Code

二、处理负值时,采用补码

P44 补码中“补”的含义,有关同余定理。

初看有点难理解,说清楚了并不难理解。(以下省略五百字,上课时再说明)

这个代码,有助于理解P45 图2

//45
program test;
var
  i:longint;
  b:shortint;
begin
  b:=7;
  for i:=1 to 16 do begin
    write( b:4, space(4) );
    writeln( binstr(b,4) );
    dec(b);
  end;
end.
View Code

三、正数与负数的转换方法

正数转换成负数:

//47-1
program test;
var
  i:shortint;
begin
  i:=%00000001; //以二进制形式输入变量值
  writeln( i ); //以十进制形式输出
  writeln( binstr(i,8) ); //以二进制形式输出
  i:=not(i); //取反,即得到 one's complement,或称一补数
  writeln( binstr(i,8) ); //一补数以二进制形式输出
  inc(i); // +1,加一后,得到 two's complement,或称二补数,就是补码
  writeln( i ); //以十进制形式输出
  writeln( binstr(i,8) ); //以二进制形式输出
end.
View Code

负数转换成正数:

//47-2
program test;
var
  i:shortint;
begin
  i:=%11111100; //这是个负数
  writeln( i ); //以十进制形式输出
  writeln( binstr(i,8) ); //以二进制形式输出
  i:=not(i); //取反,即得到 one's complement,或称一补数
  writeln( binstr(i,8) ); //一补数以二进制形式输出
  inc(i); // +1,加一后,得到 two's complement,或称二补数,就是补码
  writeln( i ); //以十进制形式输出
  writeln( binstr(i,8) ); //以二进制形式输出
end.
View Code

有个现象观察到没有?取反加1,可以不断进行下去。。

//47-2
program test;
var
  i:shortint;
begin
  i:=%11111100; //这是个负数
  writeln( i ); //以十进制形式输出
  writeln( binstr(i,8) ); //以二进制形式输出
  i:=not(i); //取反,即得到 one's complement,或称一补数
  writeln( binstr(i,8) ); //一补数以二进制形式输出
  inc(i); // +1,加一后,得到 two's complement,或称二补数,就是补码
  writeln( i ); //以十进制形式输出
  writeln( binstr(i,8) ); //以二进制形式输出
  i:=not(i)+1; writeln( i );
  i:=not(i)+1; writeln( i );
  i:=not(i)+1; writeln( i );
  i:=not(i)+1; writeln( i );
  //...
end.
View Code

四、原码、反码、补码、移码、负补

看着头晕不?其实相当简单。

1、原码

事先确定数据的位长,即二进制的位数。因为内存以字节为单位,一字节为八位,所以位长是八的倍数。

当不够位长时,前面用0补足。但如果是负数,最高位用1补足。

其中最高位为符号位:正数为0,负数为1。

以位长为八为例子:

+11 的原码为:0000 0011

-11 的原码为: 1000 0011

2、反码

在原码的基础上,最高一位为符号位,不变,其余各位取反。所谓取反,就是not(...),即0成1,1成0。

+11 的反码为:0000 0011

-11 的反码为:1111 1100

3、补码

在反码的基础上,加一,就得到补码。

+11 的补码为:0000 0011

-11 的补码为:1111 1101

可以看到,正数的原、反、补码都一样。

4、移码

移码最简单了,不管正负数,只要将其补码的符号位取反即可。

+11 的移码为:1000 0011

-11 的移码为:0111 1101

5、负补

对补码的每一位(包括符号位)求反,然后最低位加一。

+11 的补码为:0000 0011,对每一位求反,为:1111 1100,最低位加一,为:1111 1101

-11 的补码为:1111 1101,对第一位求反,为:0000 0010,最低位加一,为:0000 0011

将一个数的补码,与负补码加起来,你会发现什么?

请看代码,仅以负数举例:

program test;
var
  i,j,k:shortint;
begin
  i:=-%11; //二进制的 -11
  writeln( binstr(i,8) ); //以二进制形式输出。
  //观察输出,可以发现,内存中,以补码的形式储存数据
  j:=i xor %10000000;
  writeln( binstr(j,8) ); //移码
  k:=not(i)+1;
  writeln( binstr(k,8) ); //负补码
  writeln( binstr(i+k,8) ); //补码+负补码,产生上溢
end.
View Code

接下来,请看下一章:整数类型,如同时钟。

原文地址:https://www.cnblogs.com/xin-le/p/3980931.html