gpt4 book ai didi

C:计算出的机器 epsilon 与limits.h 不同

转载 作者:行者123 更新时间:2023-12-04 08:05:42 24 4
gpt4 key购买 nike

我尝试使用以下程序通过一个简单的 C 程序来估计机器 epsilon

#include <stdio.h>
#include <limits.h>
#include <float.h>

int main(){
float f = 1.0f;
float prev_f = 1.0f;

while( 1 + f != 1 ){
prev_f = f;
f /= 2;
}
prev_f *= 2;

printf("Calculated epsilon for float is %.10g", prev_f);
printf("The actual value is %.10f", FLT_EPSILON);
return 0;
}

我的输出在哪里
Calculated epsilon for float is 2.802596929e-45

The actual value is 0.0000001192
谁能向我解释这种偏差?它是特定于架构的吗?编译器依赖?难道我做错了什么?
编辑:
问题似乎是由于我在 gcc 中使用了 -Ofast 优化。改用 -O 可以解决问题。

最佳答案

首先,删除prev_f *= 2; .由于循环记住了 f 的值其中1 + f != 1将其存储在 prev_f 中失败,prev_f的值当循环结束时是导致 1+f 的最后一个值不等于 1,这是您想要的结果。 1
其次,允许 C 实现以比它们的名义类型更精确的方式计算浮点表达式。看来您的 C 实现正在有效地评估 1+f != 1具有无限精度(这可以通过在编译时识别 1+f != 1 评估为无限精度是正确的,如果仅当 f != 0 ,因此优化可以将其更改为 f != 0 )。因此,循环仅在 f 时终止变为零,此时前一个 f是可表示的最小正值,对于 float 常用的格式,是 2−149。 (并且您当前的代码将其加倍并打印 2−148。)请注意,(有效)无限精度仅出现在计算 1 + f != 1 中。 ,不在作业中 f /= 2; .这是因为 C 标准要求实现在执行强制转换和赋值时“丢弃”多余的精度。这为我们提供了解决此问题的方法:更改 1 + f != 1(float) (1 + f) != 1 .这将强制执行评估,就像在 float 中一样格式2
脚注
1 种。机器epsilon 有时会被错误地表述为x 的最小值,因此计算1+x 会产生大于x 的值。然而,它被定义为 1 和下一个更大的可表示值之间的差异,比如 1+𝜀。如果我们让 x 略大于 ½𝜀(例如 ½𝜀(1+𝜀)),那么由于四舍五入,计算 1+x 将产生 1+𝜀,即使 x 小于机器 epsilon。但是,如果上述问题得到修复并且浮点基数为 2,此代码将找到正确的值,因为它从未测试机器 epsilon 的这些错误候选者之一,因此从未找到一个。
2 通常,可能会出现双舍入问题:当 C 实现使用超额精度来计算表达式时,它可能会将理想的数学结果舍入到超额精度。当它被强制转换或赋值强制“丢弃”多余的精度时,它会四舍五入到标称精度。这两种四舍五入可能导致与只有一次四舍五入到标称精度的结果不同的结果。但是,在这种特殊情况下,这不是问题。

关于C:计算出的机器 epsilon 与limits.h 不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66232786/

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