c ++浮点相减误差和绝对值(c++ Floating point subtraction error and absolute values)

编程入门 行业动态 更新时间:2024-10-25 04:27:20
c ++浮点相减误差和绝对值(c++ Floating point subtraction error and absolute values)

我理解它的方式是:在c ++中用双精度减去两个double精度数时,它们首先被转换为一个有效数,从指数的幂次开始,其次是2。 那么如果相减的数字在有效数字中具有相同的指数和许多相同的数字,则可以得到错误,从而导致精度的损失。 为了测试我的代码,我编写了以下安全附加函数:

double Sadd(double d1, double d2, int& report, double prec) { int exp1, exp2; double man1=frexp(d1, &exp1), man2=frexp(d2, &exp2); if(d1*d2<0) { if(exp1==exp2) { if(abs(man1+man2)<prec) { cout << "Floating point error" << endl; report=0; } } } return d1+d2; }

然而,测试这一点我注意到一些奇怪的事情:似乎真正的错误(不是函数报告错误,而是实际计算结果)似乎取决于相减数字的绝对值,而不仅仅是等号数在有效数字中...

例如,使用1e-11作为precision prec并减去以下数字:

1)9.8989898989898-9.8989898989897:该函数报告错误,我得到了非常不正确的值9.9475983006414e-14

2)98989898989898-98989898989897:该函数报告错误,但我得到正确的值1

显然我误解了一些东西。 有任何想法吗?

The way I understand it is: when subtracting two double numbers with double precision in c++ they are first transformed to a significand starting with one times 2 to the power of the exponent. Then one can get an error if the subtracted numbers have the same exponent and many of the same digits in the significand, leading to loss of precision. To test this for my code I wrote the following safe addition function:

double Sadd(double d1, double d2, int& report, double prec) { int exp1, exp2; double man1=frexp(d1, &exp1), man2=frexp(d2, &exp2); if(d1*d2<0) { if(exp1==exp2) { if(abs(man1+man2)<prec) { cout << "Floating point error" << endl; report=0; } } } return d1+d2; }

However, testing this I notice something strange: it seems that the actual error (not whether the function reports error but the actual one resulting from the computation) seems to depend on the absolute values of the subtracted numbers and not just the number of equal digits in the significand...

For examples, using 1e-11 as the precision prec and subtracting the following numbers:

1) 9.8989898989898-9.8989898989897: The function reports error and I get the highly incorrect value 9.9475983006414e-14

2) 98989898989898-98989898989897: The function reports error but I get the correct value 1

Obviously I have misunderstood something. Any ideas?

最满意答案

如果您减去两个几乎相等的浮点值,则结果将主要反映低位中的噪声。 这里差不多相同的指数和几乎相同的数字。 例如,1.0001和1.0000几乎相等,减去它们可能会被这样的测试所捕获。 但1.0000和0.9999的差别完全相同,并且不会被像这样的测试所捕获。

此外,这不是一个安全的附加功能。 相反,这是对设计/编码错误的事后检查。 如果你减去两个非常接近的值,那么噪音就会造成错误。 修复错误。 我不反对使用类似这样的东西作为调试帮助,但请将其称为暗示这就是它的意思,而不是暗示浮点加法存在固有的危险。 此外,将检查放在加法函数内似乎过多:断言这两个值不会导致问题,然后是普通的旧浮点加法,可能会更好。 毕竟,代码中的大部分新增内容都不会导致问题,并且您最好知道问题所在的位置; 在问题点上发表声明。

If you subtract two floating-point values that are nearly equal, the result will mostly reflect noise in the low bits. Nearly equal here is more than just same exponent and almost the same digits. For example, 1.0001 and 1.0000 are nearly equal, and subtracting them could be caught by a test like this. But 1.0000 and 0.9999 differ by exactly the same amount, and would not be caught by a test like this.

Further, this is not a safe addition function. Rather, it's a post-hoc check for a design/coding error. If you're subtracting two values that are so close together that noise matters you've made a mistake. Fix the mistake. I'm not objecting to using something like this as a debugging aid, but please call it something that implies that that's what it is, rather than suggesting that there's something inherently dangerous about floating-point addition. Further, putting the check inside the addition function seems excessive: an assert that the two values won't cause problems, followed by a plain old floating-point addition, would probably be better. After all, most of the additions in your code won't lead to problems, and you'd better know where the problem spots are; put asserts in the problems spots.

更多推荐

本文发布于:2023-08-07 03:12:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1460814.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:浮点   绝对值   误差   相减   Floating

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!