如何正确划分微小的双精度数而不出现精度误差?

Ste*_*ett 11 floating-point double division floating-accuracy actionscript-3

我正在尝试诊断并修复一个可归结为X/Y的错误,当X和Y很小时会产生不稳定的结果:

在此输入图像描述

在这种情况下,cx和patharea都会顺利增加.它们的比例在高数字时是平滑的渐近线,但对于"小"数字则不稳定.显而易见的第一个想法是我们达到浮点精度的极限,但实际数字本身远不及它.ActionScript"Number"类型是IEE 754双精度浮点数,因此应该有15个十进制数字的精度(如果我读得正确).

分母(patharea)的一些典型值:

0.0000000002119123
0.0000000002137313
0.0000000002137313
0.0000000002155502
0.0000000002182787
0.0000000002200977
0.0000000002210072
Run Code Online (Sandbox Code Playgroud)

分子(cx):

0.0000000922932995
0.0000000930474444
0.0000000930582124
0.0000000938123574
0.0000000950458711
0.0000000958000159
0.0000000962901528
0.0000000970442977
0.0000000977984426
Run Code Online (Sandbox Code Playgroud)

这些中的每一个都单调增加,但如上所述,这个比例是混乱的.

在更大的数字,它平稳到平滑的双曲线.

所以,我的问题是:当你需要分开时,处理非常小数字的正确方法是什么?

我想提前将分子和/或分母乘以1000,但是不能完全解决.

有问题的实际代码是这里recalculate()功能.它计算多边形的质心,但是当多边形很小时,质心在该位置周围不规则地跳跃,并且可能与多边形相距很远.上面的数据系列是以一致的方向移动多边形的一个节点的结果(手动,这就是为什么它不是非常平滑).

这是Adobe Flex 4.5.

Jef*_*Sax 19

我认为问题很可能是由代码中的以下行引起的:

sc = (lx*latp-lon*ly)*paint.map.scalefactor;
Run Code Online (Sandbox Code Playgroud)

如果您的多边形是非常小的,然后lxlon几乎相同,因为是lylatp.与结果相比,它们都非常大,因此您减去两个几乎相等的数字.

为了解决这个问题,我们可以利用以下事实:

x1*y2-x2*y1 = (x2+(x1-x2))*y2 - x2*(y2+(y1-y2))
            = x2*y2 + (x1-x2)*y2 - x2*y2 - x2*(y2-y1)
            = (x1-x2)*y2 - x2*(y2-y1)
Run Code Online (Sandbox Code Playgroud)

所以,试试这个:

dlon = lx - lon
dlat = ly - latp
sc = (dlon*latp-lon*dlat)*paint.map.scalefactor;
Run Code Online (Sandbox Code Playgroud)

该值在数学上是相同的,但是这些项的数量级要小一些,因此误差也应该小一个数量级.

  • 天才.绝对解决问题.你应该得到的不仅仅是我的微薄投票和'正确答案'. (2认同)