使用不同舍入模式时得到的结果应以特定方式排序时,是否有任何保证(在C99标准和/或IEEE-754中)?C99 - 关于浮点舍入模式的排序的保证
例如,假设f(rm, x)
是rm
是舍入模式,x
是它的参数。我能否认为一个无缺陷的实现应该确保以下不等式?
f(FE_DOWNWARD,x) <= f(FE_TONEAREST,x) <= f(FE_UPWARD,x)
举个例子,我的机器下面的代码违背了这一假设(即使使用的是最新的glibc,版本2.21),我不知道它是否是一个错误(价值报告),或倒圆的只是一个不幸的后果错误,这意味着这种行为绝不应该依赖。
#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 “特征” :使用锵,或激活GCC的优化参数,或使用一个文本常量当调用log10f
时,而不是变量,它们都会导致一致的值。然而,这个问题仍然存在于一般情况下。
这不是GCC的一个错误,而是一个令人惊讶的结果,因为GCC直接进行优化而不涉及不精确的glibc。
为什么选择C99?为什么不是“C”或“C11”? –
主要是因为C99在'fenv.h'中引入了'FE_ *'舍入模式,但你说得对,这个问题不是C99特有的*本身*。 – anol
您的示例程序从fenv.h调用函数,但它不包含'#pragma STDC FENV_ACCESS'。这意味着编译器可以按照自己的喜好进行操作。但是,如果你添加这个编译指示,GCC会告诉你它不支持它。据我记得,它并没有在警告消息中告诉你它在命令行中支持文件相当于这个编译指示,但它确实支持这样一个命令行标志,''-frounding-math',并且如果你是幸运的是你不会发现它的一个错误。 –