首页 » 日记 » 德问注册试题分析

德问注册试题分析

德问是一个程序员的问答社区,目前注册需要先通过编程测试。测试分几个门类,只要你在任何一个门类做对一道题,就可以通过测试,进入注册阶段。我随手做了几道题,竟然全错,以至于最终做对一道后,失去了注册本身的好奇心,想把熟悉领域的题都看一遍。以下是部分试题的分析,当然不是原题。

浮点数精度问题

计算机中用二进制来实现浮点数,某些浮点数没法完全精准的表示,因此有所谓的精度问题。C的浮点数有两种类型:float, double,即常说的单精度和双精度浮点数。

准确(Accuracy)和精密(Precision)是科学、工程学、工业、统计学等领域的概念。准确指与正确的标准相符合的程度,精密则指多次量度或计算结果的一致性。在计算机领域,也常用Epsilon(精确度)来表述准确和精密。

精密度 精密度

(图片来自维基百科)。左图,准确度高但精密度低,右图精密度高但准确度低。

浮点数比较的方法中,有一种叫做精准度比较(Epsilon comparisons):

bool is_equal:
    fabs(f1 - f2) <= epsilon;

这种比较的思路在是,如果两个数值的差在很小的范围内,我们认为它们是相等的。在<float.h>中甚至还定义了几个精准度常量:FLT_EPSILON(1E-5)、DBL_EPSILON(1E-9)、LDBL_EPSILON(1E-9)。FLT_EPSILON的问题在于,如果你比较的数值很小,FLT_EPSILON就显得很大,甚至FLT_EPSILON的值都大于你要比较的数值本身!

另一种方法叫相对精度比较(Relative epsilon comparisons)。思路是:diff = fabs(f1 -f2); 如果diff比max(abs(f1), abs(f2)) * n%还小,则认为它们相等,代码如:

bool is_equal(float f1, float f2, float max_rel_diff):
    float diff = fabs(f1 - f2);
    float larg = max(fabs(f1), fabs(f2));
    return (diff <= larg * max_rel_diff ? true : false);

参考浮点数

分享

0