gpt4 book ai didi

c - 浮点运算和机器 epsilon

转载 作者:太空狗 更新时间:2023-10-29 17:20:40 26 4
gpt4 key购买 nike

我正在尝试计算 float 类型的 epsilon 值的近似值(我知道它已经在标准库中)。

这台机器上的 epsilon 值是(打印有一些近似值):

 FLT_EPSILON = 1.192093e-07
DBL_EPSILON = 2.220446e-16
LDBL_EPSILON = 1.084202e-19

FLT_EVAL_METHOD2 所以一切都以 long double 精度和 floatdoublelong double 是 32、64 和 96 位。

我试图得到一个从 1 开始的值的近似值,然后将它除以 2 直到它变得太小,用 float 类型进行所有操作:

# include <stdio.h>

int main(void)
{
float floatEps = 1;

while (1 + floatEps / 2 != 1)
floatEps /= 2;

printf("float eps = %e\n", floatEps);
}

输出不是我想要的:

float epsilon = 1.084202e-19

中间操作以最高精度完成(由于 FLT_EVAL_METHOD 的值),所以这个结果看起来是合法的。

但是,这:

// 2.0 is a double literal
while ((float) (1 + floatEps / 2.0) != 1)
floatEps /= 2;

给出这个输出,这是正确的:

float epsilon = 1.192093e-07

但是这个:

// no double literals
while ((float) (1 + floatEps / 2) != 1)
floatEps /= 2;

再次导致错误结果,如第一个:

float epsilon = 1.084202e-19

这最后两个版本在这个平台上应该是等价的,这是编译器错误吗?如果不是,发生了什么?

代码编译为:

gcc -O0 -std=c99 -pedantic file.c

gcc版本很旧,但是我在读大学,更新不了:

$ gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.5-8'
--with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs
--enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4
--enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
--with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls
--enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc
--enable-targets=all --with-arch-32=i586 --with-tune=generic
--enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu
--target=i486-linux-gnu
Thread model: posix
gcc version 4.4.5 (Debian 4.4.5-8)

gcc 的当前版本 4.7 在我的家用计算机上运行正常。也有评论说不同的版本给出不同的结果。

经过一些回答和评论,澄清了哪些行为符合预期,哪些行为不符合预期,我稍微更改了问题以使其更清楚。

最佳答案

允许编译器以它喜欢的任何更高的精度计算 float 表达式,所以看起来第一个表达式是以 long double 精度计算的。在第二个表达式中,您再次强制将结果缩小到 float

在回答您的一些其他问题和下面的讨论时:您基本上是在寻找与某种浮点类型 1 的最小非零差异。根据 FLT_EVAL_METHOD 的设置,编译器可能决定以比涉及的类型更高的精度评估所有浮点表达式。在 Pentium 上,传统上浮点单元的内部寄存器是 80 位,并且对于所有较小的浮点类型使用该精度很方便。所以最后你的测试取决于你比较 != 的精度。在没有显式转换的情况下,此比较的精度由您的编译器而不是您的代码决定。通过显式转换,您可以将比较缩小到您想要的类型。

正如您确认您的编译器已将 FLT_EVAL_METHOD 设置为 2,因此它使用最高精度进行任何浮点计算。

作为下面讨论的结论,我们有信心地说,在 4.5 版之前的 gcc 中,存在与 FLT_EVAL_METHOD=2 案例的实现相关的错误,并且至少从 4.6 版开始修复。如果在表达式中使用整数常量 2 而不是浮点常量 2.0,则在生成的程序集中省略对 float 的转换。还值得注意的是,从优化级别 -O1 开始,这些较旧的编译器会产生正确的结果,但生成的程序集却大不相同,并且只包含很少的浮点运算。

关于c - 浮点运算和机器 epsilon,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16063820/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com