捕获浮点数精度损失

问题描述

我正在用 C 编写一个小计算器来准备考试。 我知道 double 比 float 更精确,因为它为指数保留了 11 位,为有效数保留了 53 位。 对于整数,我可以执行以下操作来捕获溢出/下溢。

int sum(int a,int b,int *res){
    if((b > 0) && (a > INT_MAX + b)){
        return OVERFLOW_ERROR;
    }
    else if((b < 0) && (a < INT_MAX + b)){
        return UNDERFLOW_ERROR;
    }else {
        *res = a + b; 
    }

    return (EXIT_SUCCESS);
}

说到加倍,如果数字太大,控制台会给你“inf”或“-inf”,无论如何都不算​​太糟糕。 AFAIK,浮点数溢出,当它们失去精度时

enter image description here

那么,我的问题是,您如何处理精度损失?你能让它们“精确”吗? 他们什么时候会失去精度?

解决方法

我已经有一段时间没有正确地查看这个了,但听起来您似乎混淆了您的术语 - 溢出(数值变得太大)与精度损失(切除部分有效数)不同。

IIRC,在转换为较短的浮点格式或浮点数变得次正常/非规范化时会发生精度损失,因此如果您真的想要最大的精度,请使用long double(或查看您的编译器是否支持更广泛的浮点格式)并在计算的每个阶段检查次正规数。你不能让任何浮点数/计算“绝对精确”,除非你知道你只处理可以精确表示的数字(例如 0.5、0.25、0.125 等)并且不要做疯狂的事情,比如将两个幅度相差很大的数字相加。

通常,处理这些类型的数值错误非常复杂,并且特定于正在进行的计算 - 例如您可能会重新排列一个等式,以避免将两个值非常接近的数字相减,这样就不会lose significance

如果您没有遇到过,What Every Computer Scientist Should Know About Floating-Point Arithmetic 是一篇很棒的免​​费文章,我强烈推荐Numerical Computing with IEEE Floating Point Arithmetic 好好阅读。

,

如果您想要更精确的计算,我可以建议您使用 libgmp.a 或一些类似的库。我无法想象您将使用它的环境,除了密码学或获得越来越多的 pi 小数,但您拥有可以扩展计算机自然精度能力的库。

free42 中有一个例子,它是 hp-42s 袖珍计算器的仿真(由 Swissmicros 在其袖珍计算器系列中实现 ---see here,for info),它们使用 128 位浮点数,提供精度32 位十进制数字。

但是精度的提高有一个代价(好吧,不是简单的计算器)是操作必须在软件中解决,不再有机器指令来乘以两个浮点数。每个基本操作都必须在软件中解决,这会减慢整体计算速度。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...