一、概述
近几日觉得理解计算机的数值表示对实际编程的理解有帮助,于是就回忆整理了以前的学的基础知识,主要来自《计算机原理》与《深入理解计算机系统》,本文讨论计算机整数表示与小数的定点法表示与十进制的映射.
二、整数
我们表达一个数都是用K进制数的方式,K进制数是一个指数,无符号模式的任i位上的数都可以表示为Ki*Ki-1。计算机是用二进制表示数的,因此它位上的通项公式为2i*2i-1。整数分为无符号与有符号两种,下面分别来讨论.
1、无符号整数
二进制的无符号整数与十进制的映射,直接用2i*2i-1对每一位进行求和即可。定义一个映射函数为(数学符号不会打,因此用手写的表示):
其值域为[0,2w-1].
2、有符号整数
计算机表示有符号整数通常有三种编码方式:原码、反码、补码。但一般用补码,因此下面主要讨论补码.
2.1、原码
所谓原码,就是指最高位充当符号位,不充当实际计数。定义一个映射函数为:
其最小值就是B2Uw-2取最大值,最高位为1时,为-2w-1+1,最大值就是B2Uw-2取最大值,最高位为0时,为2w-1-1,因此其值域为[-2w-1+1,2w-1-1].
2.2、反码
所谓反码,就是最高位充当权-(2w-1-1)参与计数。定义一个映射函数为:
其最小值就是B2Uw-2取0时,最高位取1时,为-2w-1+1,最大值就是B2Uw-2取最大值,最高位取0,为2w-1-1.因此其值域为[-2w-1+1,2w-1-1].
2.3、补码
我们从原码和反码的值域可以看出,它们的负域与正域都是对称,也就是能表示2w种状态,也就是有正0与负0,因此不够完美。在某一天,一个聪明的印度人发明了补码,完美的表示了有符号整数.
所谓补码,就是最高位充当权-2w-1参与计数。定义一个映射函数为:
其最小值为B2Uw-2取0时,最高位取1时,为-2w-1,最大值为B2Uw-2取最大值,最高位取0时,为2w-1-1,因此其值域为[-2w-1,2w-1-1].从值域可以看出,负域比正域多1,从而完美表示2w-1钟状态.
2.4、根据x求-x的补码
我们设B2Tw=-x,替换并左右移动可以得B2Uw-2=2w-1-x,从这可以看出-x的0到w-2位的无符号形式为2w-1-x,我们再把最高位权算进来得2*2w-1-x,也就是2w-x,欧,我们换种写法来看看:2w-1-x+1,等于什么意思?就是取反再加1.因此根据x的补码求-x的补码就是2w-x的无符号形式,也就是对x的进行取反加1操作.
2.5、有符号补码转无符号形式.
从B2Tw与B2Uw的对比可以看出,其差别就是前者多减了一个2w-1,少加了一个2w-1,因此只要补回来就行了,为x+2*2w-1=x+2w。反之,B2Uw------>B2Tw只要减两个2w-1就行了,为x-2w.
三、定点小数
所谓定点小数就是由程序员约定小数点在数的那一位,计算机不存储小数点的位置,也就是说将小数转为整数来存储,来运算,可以优化运算的性能(整数运算要比浮点快).
1、小数与定点小数互转
我们在日常手动计算时,常常通过将小数点右移将小数转为整数,算完再小数点左移相等的位置,也就是乘或除10n(n表示移动的位数),如0.25右移两位=0.25*102=25,25左移两位=25/102=0.25。右移也就表示保留几位小数.在计算机中只不过把10换为2罢了.但是二进制的右移并不总得一个整数,有余数时需要四舍五入,因此定点小数是有精度损失的,不过保留的小数越多,精度也就越高。我们定义小数为f,保留几位小数的定点小数为Qn,综上所述得:
Qn=f*2n;
f=Qn/2n; C语言表示:int q=819;int n=1<<12;float f=(float)q/n;
2、定点小数运算
我们知道小数加减,小数点是不会变化的,因此定点小数的加减法与整数一样.而两个小数乘除法小数是会发生移动的,如0.2*0.3=0.06,1.25/0.5=2.5,而一个整数乘以一个小数,一个小数除以一个整数时小数点位不会发生移动。因此:
qn=f+f2=q1n+q2n;
qn=f-f2=q1n-q2n;
qn=f*f2=q1n*q2n/2n; q2n/2n把q2n转为f2
qn=f/f2=q1n*2n/q2n;