【问题标题】:C precision of double: compiler dependent?双精度:编译器依赖?
【发布时间】:2011-02-04 10:17:10
【问题描述】:

在我的 32 位机器(带有 Intel T7700 双核)上,对于 C 语言的 double 和 long double 类型,我有 15 个精度数字。我比较了 long double 的参数 LDBL_DIG 和 double 的 DBL_DIG 参数,它们都是 15。我使用 MVS2008 得到了这些答案。我想知道这些结果是否可能依赖于编译器,还是仅仅依赖于我的处理器?

非常感谢...

【问题讨论】:

  • 我已经测试了 Borland C++ BuilderX。最小的 long double LDBL_MIN:3.362103e-4932,最大的 long double LDBL_MAX:1.189731e+4932,long double LDBL_DIG 的精度:18。

标签: c compiler-construction precision


【解决方案1】:

一些编译器支持比 double 精度更高的 long double 格式。 Microsoft MSVC 不是其中之一。如果 15 位有效数字还不够好,那么您一开始就不应该使用浮点类型的可能性非常高。检查this thread 获取任意精度库。

【讨论】:

  • 谢谢。我听说过任意精度。 Apfloat 就是这样的库之一。在数值计算中,人们需要更高的精度,尤其是当所考虑的系统已知性能不佳时。我一直假设是计算机的处理器/架构决定了精度(我现在知道这是错误的)。您知道还有哪些其他编译器支持精度超过 15 位的 long double 类型?
  • 谢谢。该链接虽然没有提及其他 C 编译器。有趣的是,旧的 MVS 具有 80 位精度的 long double 数据类型 (msdn.microsoft.com/en-us/library/9cx8xs15.aspx)。
  • 对不起,我读得太快了。我现在看到 GNU C 编译器就是这样的编译器之一。当我们谈到任意精度时,它似乎是在软件中完成的,而不是由计算机的硬件完成的。我对吗? “一般”的 64 位机器能否提供比 32 位机器更好的 long double 精度?抱歉,我对此事的了解有限。
  • 这样的格式没有硬件支持,与“double”相比,它会慢得多。
【解决方案2】:

它们可能依赖于编译器,但一般来说,它们只依赖于架构。特别是如果编译器使用相同的包含文件,这些可能不会有所不同。不过,如果您想编写可移植的代码,最好检查一下它们。

【讨论】:

  • 谢谢。我将尝试使用另一个编译器(可能是 Borland)并进行测试。
【解决方案3】:

没错。这些是依赖于实现的。 C 标准的唯一保证是:

  1. floatdouble 的子集,doublelong double 的子集 (6.2.5/10)
  2. FLT_RADIX ≥ 2 (5.2.4.2.2/9)
  3. FLT_DIG ≥ 6, DBL_DIG ≥ 10, LDBL_DIG ≥ 10
  4. FLT_MIN_10_EXP, DBL_MIN_10_EXP LDBL_MIN_10_EXP ≤ -37
  5. FLT_MAX_10_EXP, DBL_MAX_10_EXP, LDBL_MAX_10_EXP ≥ +37
  6. FLT_MAX, DBL_MAX, LDBL_MAX ≥ 1e+37 (5.2.4.2.2/10)
  7. FLT_EPSILON ≤ 1e-5, DBL_EPSILON ≤ 1e-9, LDBL_EPSILON ≤ 1e-9 (5.2.4.2.2/11)
  8. FLT_MIN, DBL_MIN, LDBL_MIN ≤ 1e-37

C 标准允许处理 long double = double

【讨论】:

  • 感谢这些有用的值。括号中的数字在第一行代表什么(6.2.5/10)?
  • @yCalleecharan:它们是 C 标准的条款。
【解决方案4】:

虽然 C 标准不要求这样做,但它强烈建议 floatdouble 分别是标准的 IEEE 754 单精度和双精度浮点类型。它们位于任何在硬件中支持它们的架构上(这意味着几乎无处不在)。

long double 的情况稍微复杂一些,因为没有多少架构支持高于双精度的浮点类型。该标准要求long double 具有至少与double 一样多的 范围和精度。这意味着如果架构不再支持任何东西,long double 类型与double 相同。即使它确实(如 x87),一些编译器仍然使 long double 等效于 double(如 M$VC),而其他编译器将扩​​展精度类型公开为 long double(如 Borland和 GCC)。

即使编译器公开了扩展精度类型,“扩展精度”的确切含义仍然没有标准。在 x87 上,这是 80 位。其他一些体系结构具有 128 位四精度类型。即使在 x87 上,一些编译器也有 sizeof(long double) = 10,而另一些编译器将其填充为对齐,因此它是 12 或 16(如果 long doubledouble,则为 8)。

所以底线是,long double 的实现因平台而异。唯一可以确定的是,它至少相当于double。如果你想编写可移植的代码,不要依赖它的表现形式——让它远离接口和二进制 I/O。不过,在程序的内部计算中使用 long double 是可以的。

【讨论】:

  • 感谢您提供有用的信息。我将尝试使用 Borland,看看我是否与 MVS2008 有任何不同。
【解决方案5】:

您还应该知道,某些 CPU 的浮点单元支持多级精度以获得中间结果,并且可以在运行时控制此级别。应用程序已受到诸如在库调用期间选择较低精度级别并忘记恢复设置的错误版本的 DirectX 库之类的事情的影响,从而影响调用者中以后的 FP 计算。

【讨论】:

  • 谢谢。但是(新的?)英特尔处理器在数学计算方面应该是更好的处理器。我对吗?您提到了有缺陷的 DirectX 库的影响。作为程序员,我们对此有任何控制权吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多