后两种舍入方法据说是为了数值计算中的区间算法,但很少听说哪个商业软件使用区间算法。
3、十进制小数与二进制小数的相互转换
先看看十进制数与二进制数如何互相转换。用下标表示数的基(base),即d10表示十进制数,b2二进制数。则一个具有n+1位整数m位小数的十进制数d10表示为:
例3:
同理,一个具有n+ 1位整数m位小数的二进制数b2表示为:
例4:
二进制数转换成十进制数,比较容易,如例4。
十进制数转换成二进制数,是把整数部分和小数部分分别转换,整数部分用2除,取余数,小数部分用2乘,取整数位。
例5:把(13.125)10转换成二进制数
整数部分:,小数部分:
因此,
说明:C/C++语言的scanf()函数一般不采用这种方法。
一个十进制数能否用二进制浮点数精确表示,关键在于小数部分。我们来看一个最简单的小数能否精确表示。按照乘以2取整数位的方法,有:
得到一个无限循环的二进制小数,用有限位无法表示无限循环小数,因此,无法用IEEE 754浮点数精确表示。从中也可以看到:由于
,这四个数也无法精确表示。同理:
也无法用IEEE 754浮点数精确表示。
结论1:的9个小数中,只有0.5可以精确表示:。
可以把这个结论推广到一般情况:
结论2:任何下面的十进制数都无法用IEEE 754浮点数精确表示,必定存在误差。
如果的整数部分能精确表示且该数在浮点数的精度范围之内,则该数可以精确表示。
4、二进制小数能精确表示的十进制小数的基本规律
上述结论是由十进制数向二进制数转换而得到的,下面从二进制数向十进制数转换的角度来推演:
可以一直算下去,得到一个基本规律
结论3:一个十进制小数要能用浮点数精确表示,最后一位必须是5,因为1 除以2永远是0.5,当然这是必要条件,并非充分条件。
一个m位二进制小数能够精确表示的十进制小数有多少个呢?当然是个。推演如下:
一位二进制小数能够精确表示的小数只有个:。
两位二进制小数能够精确表示的小数有个:。
三位二进制小数能够精确表示的小数有个:
…
m位二进制小数能够精确表示的十进制小数就是个。而m位十进制小数有个,因此,能精确表示的十进制小数的比例是,m越大,比例越小。以常用的单精度和双精度浮点数为例,m分别是24和53,则比例为:和,小到可以忽略不计。
5、FAQ:C/C++库函数函数printf()是如何忽悠我们的?
Q:既然绝大部分浮点小数都不能精确表示十进制小数,为什么printf()经常能打印出准确的值?
A: 因为IEEE 754对二进制到十进制的转换有明确规定,见前面2.d)。而且函数printf()默认情况下只打印7位有效数字,在误差不大的情况下是没有问题的,但 是,我们经常见到这样的结果“.xxxx999999”。用printf(“%.17lf”, …);可以让浮点数显出原形。
6、与IEEE 754相关的标准
本文的结论基于IEEE 754标准,另外一个标准是IEEE 854,这个标准是关于十进制浮点数的,但没有规定具体格式,所以很少被采用。另外,从2000年开始,IEEE 754开始修订,被称为IEEE 754R(),目的是融合IEEE 754和IEEE 854标准,已经在工作组内进行表决,还没有被IEEE表决通过,估计也快了。该标准在浮点格式方面的修订如下:
a) 加入了16位和128位的二进制浮点数格式。
b) 加入了十进制浮点数格式,采用了IBM公司()提出的格式,Intel公司也提出了自己的格式,但未被采纳,只留了口子。(标准从来都是企业利益博弈的产物)。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/tongxinshuyu/article-30023-3.html
想去存