舍入浮点结果

时间:2015-07-15 23:33:32

标签: c floating-point double rounding

我有两个浮点(双)值 a b ,我希望添加它们以获得结果 c

我知道 c 会以某种方式被近似,因为一切都是有限的精度。现在,我想要向下舍入' c ,意味着浮点 c 不大于浮点 a b 的实际总和,或 c < = a + b

我该怎么做?我想到了以下c代码,但我不确定答案是否符合我的要求。

c = nextafter(a + b, bigNegativeNumber)

同样的问题是乘法而不是加法。 :)

PS。如果有帮助, a b 总是非负数。

编辑: c 也应该是一个浮点

2 个答案:

答案 0 :(得分:1)

根据您的描述,您似乎想要控制浮点运算的舍入模式。 C99通过头文件fenv.h中提供的功能支持此功能。您可能需要指示编译器打开C99支持,您可能需要指示它以符合IEEE-754的方式执行浮点运算。下面是一个最小的示例,显示如何使用截断(向零舍入)执行double加法。由于您的操作数已知为正数,因此相当于向下舍入(向负无穷大)。

#include <stdio.h>
#include <stdlib.h>
#include <fenv.h>

#pragma STDC FENV_ACCESS ON

double dadd_rz (double a, double b) 
{
    double res;
    int orig_mode = fegetround ();
    fesetround (FE_TOWARDZERO);  // set rounding mode to truncate
    res = a + b;
    fesetround (orig_mode);      // restore rounding mode
    return res;
}

int main (void)
{
    double a = 0x1.fffffffffffffp1023;
    printf ("                  a = %20.13a\n", a);
    printf ("                a+a = %20.13a\n", a + a);
    printf ("round_to_zero (a+a) = %20.13a", dadd_rz (a, a));
    return EXIT_SUCCESS;
}

上述程序的输出看起来应该是这样的(注意无限的打印是依赖于实现的):

                  a = 0x1.fffffffffffffp+1023
                a+a = 0x1.#INF000000000p+0
round_to_zero (a+a) = 0x1.fffffffffffffp+1023

答案 1 :(得分:0)

棘手的问题。

@EOF上面对“向0舍入”的评论很好并且会提供最佳结果。

#ifdef _ _STDC_IEC_559_ _ 
    fesetround(FE_DOWNWARD);
    c = a + b;
#else
   #error unable to set rounding mode
#endif
OP的原始方法也很接近。任何好的编译/处理器都应该在0.5或1.0 ULP(取决于舍入模式)下创建最佳答案。它肯定会创建一个总和c2小于算术a+b,但c 可能也符合要求。

c = a + b
c2 = nextafter(c, -DBL_MAX);

c = floor(a + b)无法正常工作,因为a的数量远远大于某些小的负数b,因此计算的总和仍然很简单a并且算术 c <= a + b