首页 > 程序设计, 计算机 > 计算机中浮点数的舍入

计算机中浮点数的舍入

学过计算机组成原理的同学都知道在计算机中,浮点数是通过3个部分来表征的,1个bit的符号位,k个bit的指数位和n个bit的有效数位,对于C语言中的float和double,k、n值分别是8、23和11、52。

我们可以想象一下,表征浮点数的bit是有限的,因而其组合也是有限的,是无法完全表征所有实数的,事实上,连一些10进制下看上去很简单的数也都无法精确表示。比如,你可以试一下下面几行代码:

1
2
3
4
5
6
7
#include <stdio.h>
int main()
{
	double a = 0.1;
	printf("%.20lf",a);
	return 0;
}

你会看到输出的其实是0.10000000000000001000。

正是由于很多实数无法精确表示,所以在计算机处理浮点数的时候,需要进行大量的舍入操作,那么计算机默认是采用什么样的舍入策略呢?

以前我一直以为计算机采用的就是人们日常所熟悉的“四舍五入”法则,因为在printf函数中,如果指定输出精度小于实际精度的话,输出的结果就是按四舍五入产生的。其实这是printf函数故意设计成这样以符合人们的日常习惯的。

实际计算机中,当需要进行舍入操作时,运用是一种叫“round-to-even”的策略,即“向偶数舍入”,举个简单的例子就可以明白了,比如1.235和1.245,舍入后都是1.24, 也就是说要使得舍入后的最后一位有效数字是偶数。

为什么要采用这样的策略,而不直接使用我们已经习惯的“四舍五入”呢。原因在于,在进行舍入的时候,最后一位数字从1到9, 舍去的有1,2,3,4;正好可以和进位的9,8,7,6相对应,而5却被单独出来了,如果我们采用四舍五入每次都将5进位的话,在进行一些大量数据的统计时,就会累积比较大的偏差,而如果采用”round-to-even”的策略,在巨大多数情况下,5舍去还是进位的几率差不多,统计时产生的偏差也就相应要少一些了。

  1. andi
    2012年1月10日00:02 | #1

    其实这是printf函数故意设计成这样以符合人们的日常习惯的。 好像不是四舍五入吧。”%.2f”多试试。 囧

  2. andi
    2012年1月10日00:32 | #2

    是四舍五入。囧 精度问题。

    int main() {
    printf(“%.20lf %.2f\n”, 0.015, 0.015); // 0.01499999999999999900 0.01
    printf(“%.20lf %.2f\n”, 0.025, 0.025); // 0.02500000000000000100 0.03
    printf(“%.20lf %.2f\n”, 0.035, 0.035); // 0.03500000000000000300 0.04
    printf(“%.20lf %.2f\n”, 0.045, 0.045); // 0.04499999999999999800 0.04
    printf(“%.20lf %.2f\n”, 0.055, 0.055); // 0.05500000000000000000 0.06
    printf(“%.20lf %.2f\n”, 0.065, 0.065); // 0.06500000000000000200 0.07
    printf(“%.20lf %.2f\n”, 0.075, 0.075); // 0.07499999999999999700 0.07
    printf(“%.20lf %.2f\n”, 0.085, 0.085); // 0.08500000000000000600 0.09
    printf(“%.20lf %.2f\n”, 0.095, 0.095); // 0.09500000000000000100 0.10
    return EXIT_SUCCESS;
    }

  1. 本文目前尚无任何 trackbacks 和 pingbacks.
注意: 评论者点击“回复”(即默认使用'@user '的方式),系统会给您回复的人发一封通知邮件,使用'@all ',则会将评论发送给之前所有其它评论者。您填写的邮箱不会被泄露,只有博主在后台才能看到。