向下舍入浮点结果

Round Down a Floating Point Result

我有两个浮点(双精度)值 ab,我希望将它们相加以获得结果c

我知道 c 会以某种方式被近似,因为一切都是有限精度的。现在,我要'round down'c,意思是浮点数c不大于浮点数的实数和ab,或 c <= a + b.

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

c = nextafter(a + b, bigNegativeNumber)

相同的问题适用于乘法而不是加法。 :)

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

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

根据您的描述,您似乎想控制浮点运算的舍入模式。头文件 fenv.h 中提供的功能在 C99 中支持这一点。您可能需要指示您的编译器打开 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

一个棘手的问题。

@EOF 上面对 "round toward 0" 的评论很好,将提供最佳结果。

#ifdef _ _STDC_IEC_559_ _ 
    fesetround(FE_DOWNWARD);
    c = a + b;
#else
   #error unable to set rounding mode
#endif

OP的原始方法也很接近。任何好的 compilation/processor 都应该在 0.5 或 1.0 ULP(取决于舍入模式)中为 with 创建最佳答案。它肯定会创建一个总和 c2 小于算术 a+b,但是 c 可能 也满足要求。

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

c = floor(a + b) 将不起作用,因为 a 的幅度可能远大于一些小的负值 b,因此计算的总和仍然很简单 a 并且失败算术 c <= a + b.