【问题标题】:math.h default rounding mode not clearmath.h 默认舍入模式不清楚
【发布时间】:2013-05-26 22:58:38
【问题描述】:

我正面临着关于 float 舍入和转换为 int 的非常奇怪的事实。

正如这里所说: http://www.gnu.org/software/libc/manual/html_node/Rounding.html

四舍五入到最接近的可表示值是默认的舍入模式。但好像不是。

所以我创建了这个简单的程序:

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

int a;
double b;

main() {
  b=1.3; a=b; printf("%f %d\n",b,a);
  b=1.8; a=b; printf("%f %d\n",b,a);
  b=-1.3; a=b; printf("%f %d\n",b,a);
  b=-1.8; a=b; printf("%f %d\n",b,a);
  printf("%d %d %d\n",fegetround(),FE_TONEAREST,FE_TOWARDZERO);
}

程序是用 gcc-4.7 (debian)、cygwin gcc 和 Visual Studio 编译的。输出是一样的,只是FE_TOWARDZERO的定义改变了。

程序输出:

 1.300000 1
 1.800000 1
-1.300000 -1
-1.800000 -1
0 0 3072

所以我们可以清楚地看到,在所有经过测试的编译器中,舍入模式都设置为FE_TONEAREST(默认),但它们都向零舍入。

为什么?

PS:是的,我可以使用Math.round(),但我想知道为什么会这样。

【问题讨论】:

    标签: c math floating-point type-conversion rounding


    【解决方案1】:

    好的,我发现了为什么会发生这种情况的问题。 如此处所述:

    http://software.intel.com/en-us/articles/fast-floating-point-to-integer-conversions

    在章节中

    A Closer Look at Float-to-Int Conversions
    

    从浮点数转换为 32 位的问题 整数源于 ANSI C 标准,该标准规定了转换 应该通过截断数字的小数部分来实现 并保留整数结果。正因为如此,每当 Microsoft Visual C++ 6.0 编译器遇到 (int) 或 (long) cast 时,它会插入对 _ftol C 运行时函数的调用。这 函数将浮点舍入模式修改为“截断”, 执行转换,然后将舍入模式重置为其 施法前的原始状态。

    【讨论】:

      【解决方案2】:

      因为舍入模式适用于浮点舍入函数。转换为 int 总是会被截断。

      【讨论】:

      • 我不明白。当我想对浮点进行舍入时,我可以使用 Math.round()、ceil() 或 floor()。还是我看错了?
      • @Mihalko 你不明白int a = (int)aFloat;int a = round(aFloat); 是不一样的。
      • 但是在将浮点数转换为整数时使用了 FP 协处理器中的舍入模式。无论如何,我在这里找到了答案:software.intel.com/en-us/articles/… 在“仔细观察浮点到整数的转换”一章中
      • @Mihalko 不,不是,或者至少不是这种舍入模式。无论如何,转换为 int 总是会被截断。
      • @Mihalko 在 C 标准库中设置的舍入模式不会影响 CPU。 我应该如何编写它以便您理解?它只影响 C 标准库中的函数。
      猜你喜欢
      • 2016-03-29
      • 1970-01-01
      • 2016-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多