是否有任何保证(在C99标准和/或IEEE-754中)使用不同舍入模式得到的结果应以特定方式排序?
例如,让f(rm, x)成为一个函数,其中rm是舍入模式,而x是其参数。我是否可以认为一个无bug的实现应该确保以下不平等?

f(FE_DOWNWARD,x) <= f(FE_TONEAREST,x) <= f(FE_UPWARD,x)

举个例子,我机器上的以下代码与这个假设相矛盾(即使使用了最新的glibc版本2.21),我想知道这是一个bug(值得报告),还是仅仅是舍入错误的不幸结果,这意味着永远不应该依赖这种行为。
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <fenv.h>
#include <gnu/libc-version.h>

void set_round(int rm) {
  // checks that the rounding mode has been successfully set
  if (fesetround(rm)) { perror("setround"); exit(1); }
}

int main() {
  printf("GNU libc version: %s\n", gnu_get_libc_version());
  float x = 3;
  set_round(FE_TONEAREST);
  float r = log10f(x);
  printf("nearest:     r = %g (%a)\n", r, r);

  set_round(FE_DOWNWARD);
  r = log10f(x);
  printf("downward:    r = %g (%a)\n", r, r);

  set_round(FE_UPWARD);
  r = log10f(x);
  printf("upward:      r = %g (%a)\n", r, r);

  set_round(FE_TOWARDZERO);
  r = log10f(x);
  printf("toward zero: r = %g (%a)\n", r, r);
  return 0;
}

输出:
GNU libc version: 2.21
nearest:     r = 0.477121 (0x1.e89278p-2)
downward:    r = 0.477121 (0x1.e8927ap-2)
upward:      r = 0.477122 (0x1.e8927cp-2)
toward zero: r = 0.477121 (0x1.e8927ap-2)

编辑:这个具体的例子是一个GCC“feature”1:使用Clang,或者激活GCC的优化标志,或者在调用log10f时使用文本常量而不是变量,所有这些都会产生一致的值。然而,这个问题仍然存在于一般情况下。
1 GCC并不认为这是一个bug,而是一个令人惊讶的结果,因为GCC直接执行优化而不涉及不精确的glibc。

最佳答案

没有这样的保证。
一些数学库试图仅对数学库函数满足此约束,但任何标准都不要求这种行为,而且这种情况非常罕见(即使是大多数试图提供这种约束的库也存在妥协和错误)。
对于不在数学库中的函数来说,试图遵从该属性几乎是不可能的,而且大多数都是无用的,因此基本上是闻所未闻的。
IEEE-754(2008)建议(但不要求)正确舍入数学库函数的特定子集(或提供正确舍入的版本),这意味着要查找的属性。然而,这项建议目前没有得到广泛执行。

关于c - C99-保证有关浮点舍入模式的顺序,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31118929/

10-13 22:33