计算机基础,数值表示

2,969 阅读5分钟

数制和编码

十进制数转成二进制

十进制转二进制,整数采用“整除取余,上右下左”,而小数部分则是“乘基取整,上左下右”,例子:

十进制的100转成二进制是:1100100

十进制的1.875转成二进制步骤如下:

1、整数部分是1,转成二进制是1

2、 小数部分是0.875

0.875 * 2 = 1.75    ... 取1

0.75 * 2 = 1.5      ... 取1

0.5 * 2 = 1.0       ... 取1

因此小数部分转成二进制是从上往下以此 0.111,故十进制的1.875转成二进制是1.111。

这就是大体的步骤,网上也有很多相似的博客,我就写得简单一点。

细心的同学可能会发现,假如小数最后一位不是5的小数转成二进制是无法准确表示的,比如1.3。其实,根本的原因是 1/(2^n)的最后一位必定是5,如1/8 = 0.125 1/32 = 0.03125 等等。

那么如果二进制数转成十进制呢?也很简单,就不写了

补码与转换

众所周知,整数都采用补码的形式存储(正整数原码补码一致),这里说下负数的补码表示:

如:十进制的-125,假设机器数是8位,则 125 = 127 - 2 = 1111 1101B 125的二进制表示

[-125]补码 = 2^8 - 1111 1101B = 1111 1111B - 1111 1101B +1B = 0000 0011B

0000 0011B 符号位置为1 即变成 1000 0011B,即为十进制-125的补码表示

那么如果知道补码,如何求真实值(即现实世界中的数值)呢?

很简单,例如(假设机器数是8位): 看符号位,最高位如果为1,则表示负数,则

1000 0011B的真实值 = -2^7 + 2^1+1 = -128 + 2 + 1 = -125

如果补码是0000 0011B呢?

0000 0011B的真实值 = 2+1 = 3

浮点数

任何实数都可以用一条公式来表示:

X = (-1)^S * M * R^E   

R是基数(如2、8、10、16),M是一个二进制定点小数,称为X的尾数,E是二进制定点整数,称为指数或阶,S是符号位。只要确定S、M、E三个数,这样的X就称为浮点数。

一般来说,偏置常数的取值是 2^(n-1),或者是2^(n-1)-1 (n是机器位数),比如8位机器数,偏置常数就是2^7 = 128或者是127,而IEEE754标准规定单精度32位浮点数的偏置常数是127,双精度64位浮点数偏置常数是1023。

IEEE754标准规定单精度浮点数是由32位组成,其中包含1位符号位,8位移码(移码就是补码符号位取反,移码用来表示浮点数的阶),以及23位尾数。(M表示小数部分,计算真值的时候需要记得加上隐含的1)

机器数转真值

具体用一个例子来说明: 如:浮点数的机器值的16进制表示为BEE00000H,则求它的真是值

BEE00000H = 1011 1110 1110 0000 0000 0000 0000 0000B

则套用公式 X = (-1)^S * M * R^E R是基数2

S是首位 1 移码是除了首位后面取8位,也就是 01111101,这是E的值, 01111101B = 125(十进制),所以 浮点数的指数 = 125 - 127(偏置常数)= -2 所以指数的值是-2 M是剩下的 110 0000 0000 0000 0000 0000 = 1 * 2^-1 + 1 * 2^-2 = 0.75,别忘了隐含的1,所以M的值是1+0.75 = 1.75,因此

X的真值 = (-1)^1 * 1.75 * 2^-2 = -0.4375

反之如何求值?真值如何求机器数?

例如:

-0.4375转成二进制得:-0.0111 = -1.11 * 2^(-2) (转成标准格式)

负数因此 S是1
指数为-2,则移码为 127(偏置常数)+(-2) = 125,二进制表示为 01111101,即为E的值
M值为小数部分,所以是 11(省略了前面的1,这个1是隐含的),在补上剩下的21个0即可,

也即:1 01111101 11000000000000000000000

数值比较?

C语言中,若同时出现无符号数和带符号数,则C编译器会将带符号数转成无符号数再进行比较。 如:

-1 < 0 带符号数比较,结果为true

-1 < 0U 转成无符号数比较 -1的二进制表示为
11...1(n个1),转成无符号数之后,就变成2^n - 1的值了,因此比0大,所以结果为false

又如:

2147483647 > (int)2147483648U 结果是false

因为2147483648 转成带符号数比较,2147483648等于2^31,由于最高位是1,所以最终被转成 -2147483648 与 2147483647 比较,因此结果为false

另外,需要注意的是对于计算机 ISO C90 与ISO C99的表示数值方式有点区别:

在C90 的机器中, 0 - 2^31-1 为int类型 与C99一致 然而,2^31 - 2^32 -1 区间的值会被转成unsigned int 无符号数,因此在C90的机器中,会出现

-2147483648 < 2147483647 结果为false

因为-2147483648会被转成无符号数(32位无符号数区间为0到4294967295),而-2147483648的二进制表示为 100...0(共31个0),因此转成无符号数的十进制值是2147483648,是正数,比2147483647大 ,因此结果为false.

结语:纯一字字敲出来,如果有误,欢迎各位斧正!