是否“epsilon”真的可以保证浮点计算中的任何东西吗? [英] Does "epsilon" really guarantees anything in floating-point computations?

查看:172
本文介绍了是否“epsilon”真的可以保证浮点计算中的任何东西吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了让这个问题变得简单,我们假设我想计算 float 上的表达式 a /(b-c) > s。



为了确保结果有意义,我可以检查 b c 等于:


$ b

float EPS = std :: numeric_limits< float> :: epsilon(); (b-c)> EPS ||(c-b)> EPS)
{
return a /(b-c);
}

但是我的测试表明仅仅保证有意义的结果或者不失败如果可能的话提供结果。



案例1:



  a = 1.0f; 
b = 0.00000003f;
c = 0.00000002f;

结果: if条件不符合,但表达式会产生一个正确的结果100000008(至于浮点数的精度)。
$ b $ h1例2:

  a = 1e33f; 
b = 0.000003;
c = 0.000002;

结果:符合if条件,但表达式不产生有意义的结果 + 1.#INF00



我发现检查结果更可靠, :
$ b

const float INF = numeric_limits< float> :: infinity();
float x = a /(b - c);
if(-INF< x& x& x< INF)
{
return x;
}

但是,那么为什么每个人都说epsilon是好的使用?

解决方案

处理浮动数据时必须使用一个epsilon是程序员的一个膝盖反应,通常是比较(不仅仅是零)。

这通常是无用的,因为它不会告诉你如何最小化四舍五入的传播错误,它并不告诉你如何避免取消或吸收问题,甚至当你的问题确实与两个浮点数的比较有关时,它并不告诉你ε值是多少是正确的如果您还没有阅读

/ncg_goldberg.htmlrel =nofollow noreferrer>每个计算机科学家应该知道什么是浮点运算,这是一个很好的起点。除此之外,如果您对示例中除法结果的精度感兴趣,则必须估计 因为确实如果 bc 很小,一个小的绝对误差对应于结果的绝对误差。如果你担心的只是分工不应该溢出,那么你的测试(结果)是正确的。没有理由使用浮点数测试空分隔符,只是测试结果的溢出,它捕获除数为空的情况和除数太小以至于不能用任何精度。



关于舍入误差的传播,存在专业分析仪,可以帮助您估算,因为手工操作是一件繁琐的事情。


To make the problem short let's say I want to compute the expression a / (b - c) on floats.

To make sure the result is meaningful, I can check if b and c are in equal:

float EPS = std::numeric_limits<float>::epsilon();
if ((b - c) > EPS || (c - b) > EPS)
{
    return a / (b - c);
}

but my tests show it is not enough to guarantee either meaningful results nor not failing to provide a result if it is possible.

Case 1:

a = 1.0f;
b = 0.00000003f;
c = 0.00000002f;

Result: The if condition is NOT met, but the expression would produce a correct result 100000008 (as for the floats' precision).

Case 2:

a = 1e33f;
b = 0.000003;
c = 0.000002;

Result: The if condition is met, but the expression produces not a meaningful result +1.#INF00.

I found it much more reliable to check the result, not the arguments:

const float INF = numeric_limits<float>::infinity();
float x = a / (b - c);
if (-INF < x && x < INF)
{
     return x;
}

But what for is the epsilon then and why is everyone saying epsilon is good to use?

解决方案

"you must use an epsilon when dealing with floats" is a knee-jerk reaction of programmers with a superficial understanding of floating-point computations, for comparisons in general (not only to zero).

This is usually unhelpful because it doesn't tell you how to minimize the propagation of rounding errors, it doesn't tell you how to avoid cancellation or absorption problems, and even when your problem is indeed related to the comparison of two floats, it doesn't tell you what value of epsilon is right for what you are doing.

If you have not read What Every Computer Scientist Should Know About Floating-Point Arithmetic, it's a good starting point. Further than that, if you are interested in the precision of the result of the division in your example, you have to estimate how imprecise b-c was made by previous rounding errors, because indeed if b-c is small, a small absolute error corresponds to a large absolute error on the result. If your concern is only that the division should not overflow, then your test (on the result) is right. There is no reason to test for a null divisor with floating-point numbers, you just test for overflow of the result, which captures both the cases where the divisor is null and where the divisor is so small as to make the result not representable with any precision.

Regarding the propagation of rounding errors, there exists specialized analyzers that can help you estimate it, because it is a tedious thing to do by hand.

这篇关于是否“epsilon”真的可以保证浮点计算中的任何东西吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆