Math 跨积操作后精确比较浮动

Math 跨积操作后精确比较浮动,math,floating-point,integer,geometry,precision,Math,Floating Point,Integer,Geometry,Precision,这是关于精确执行以下比较: CrossProduct(P - P0, P1 - P0) >, < or == 0 其中0我的浮动解决方案 想象一个由3x3个点组成的小网格,在第二位截断或四舍五入: (0.00, 1.00) (0.50, 1.00) (1.00, 1.00) (0.00, 0.50) (0.50, 0.50) (1.00, 0.50) (0.00, 0.00) (0.50, 0.00) (1.00, 0.00) 如果我们将任何浮点值进一步解释为一个错误(因为并非所

这是关于精确执行以下比较:

CrossProduct(P - P0, P1 - P0) >, < or == 0

其中0我的浮动解决方案

想象一个由3x3个点组成的小网格,在第二位截断或四舍五入:

(0.00, 1.00) (0.50, 1.00) (1.00, 1.00)
(0.00, 0.50) (0.50, 0.50) (1.00, 0.50)
(0.00, 0.00) (0.50, 0.00) (1.00, 0.00)
如果我们将任何浮点值进一步解释为一个错误(因为并非所有小数都可以用浮点精确描述),则叉积运算的最小绝对值为:

|CrossProduct((0.50 + error1, 0.00 + error2), (0.00 + error3, 0.50 + error4))| = 
(0.50)² + 0.50(error1 + error4) + error1 * error4 + error2 * error3

寻找ε

如果浮点数被四舍五入,则为-0.005零,当小于零时为-0。因此,这个怀疑区需要另一种方法

还有一个区域100%确定结果为零,即当结果结论

如果上面使用浮点比较叉积的方法是绝对正确的,那么在整数上使用浮点仍然有一些优点和缺点

在整数上使用浮点的第一个缺点是早期截断或舍入,这可能使点0.3333f变成0.3300000+错误

如果终点结果的精度远不如没有误差那么重要,并且每次都必须重复使用p(i,j)到p(x,y)公式的麻烦/性能是值得的,那么这应该不是一个问题

另一方面,使用64位浮点上的64位整数可以实现非常高的精度。最大整数分辨率计算为2^15,这给出了(1/2^15)=3.05E-5的单位增量。这已经比64位浮点给出的有效数字还要多。64位整数将产生更高的精度:4.65E-10


我自己可能会坚持使用intergers解决方案,并接受每次从int点重新计算浮点的麻烦/性能。但无论如何,这可能对很多在浮动方面有困难的人有用。这是可能的,但并不容易。本文讨论计算几何中的谓词


但是,如果某些几何任务需要它,您可以描述它。例如,如果我们想对多边形进行布尔运算,我们不需要求直线交点和方向的精确正确解。我们只需要所用谓词的可重复性。它可以更容易地完成。

使用24个有效位浮动存储尾数。这意味着点集中最大坐标的相对误差至少为2^-24

因此,除非您的问题具有非均匀结构(靠近原点的点密度较大),否则将所有坐标重新缩放到[-2^24,2^24]x[-2^24,2^24]域并截断为整数是有意义的,永远忘记浮点。甚至还有7个备用精度位,您可以映射到[-2^31,2^31]x[-2^31,2^31],这远远超出您的需要

这样,使用64位整数精确计算有符号区域,并且没有溢出

您可能不愿意牺牲一些重要的小坐标位,但在实际情况下,这并不重要


如果坐标是双精度的,则有2^53个尾数位,其中很大一部分一定是噪声。然后检查有效位的实际数量是有意义的。你会意识到你已经受够了。。。浮动。

标题“寻找ε”下面的第一段是胡说八道。首先,没有理由相信以浮点数表示实际值的近似值仅为1/2 ULP或1 ULP。这取决于之前的计算。更重要的是,这种精度损失已经发生了!那是过去的事了。现在太晚了。你应该关注的是在你的控制下的操作的准确性损失,交叉产品的加法和乘法。第二“错误需要考虑实际的浮子数可能不是精确地0.50,但是0.5万01F或0.499 99 99 F”是双重荒谬的。您已经在讨论用浮点表示实数的错误。您不需要添加第二个错误“因为浮点是不精确的”。表示错误就是你的方程式的内容。如果你对浮点感兴趣,你应该阅读(免费)或更好的《浮点算术手册》(价格昂贵,但你可能会免费找到非法的PDF)。如果你没有时间,TLDR就是你使用的浮点类型是用二进制表示的,你应该考虑到这点,而不是计算错误。你发现IEEE 754双精度性能比32位整数差的事实是另一个提示。通常,如果您的双精度计算无法很好地处理假设的53位整数也可以解决的问题,则您使用的浮点是错误的。有关浮点算术中
a*b+c*d
的精确计算,请参阅
CrossProduct(lhs, rhs) = lhs.x * rhs.y - lhs.y * rhs.x
P = (i, j)
a * b - c * d <= int.MaxValue
maxResolution * maxResolution + maxResolution * maxResolution <= int.MaxValue
2 * maxResolution² <= int.MaxValue
maxResolution <= (int.MaxValue / 2)^(1/2)

For integers : maxResolution = 2^15 + 1
For longs : maxResolution = 2^31 + 1
(0.00, 1.00) (0.50, 1.00) (1.00, 1.00)
(0.00, 0.50) (0.50, 0.50) (1.00, 0.50)
(0.00, 0.00) (0.50, 0.00) (1.00, 0.00)
|CrossProduct((0.50 + error1, 0.00 + error2), (0.00 + error3, 0.50 + error4))| = 
(0.50)² + 0.50(error1 + error4) + error1 * error4 + error2 * error3
CrossProduct((0.4899998, 0.00), (0.00, 0.4899998)) = 0.4899998² - 0.00² = 0.240099804
if(CrossProduct >= ZERO) -> CrossProduct > 0
if(CrossProduct <= -ZERO) -> CrossProduct < 0
else -> CrossProduct == 0
ZERO = (delta - maxError)², 
maxError = digit n of truncation + 2E-7.
(float)(xmax +- xmin) == (real)(xmax +- xmin)    // float number sum of P0 and P1 equals real number sum of P0 and P1
(float)(xmax +- xmax) == (real)(xmax +- xmin)
(float)(xmin * ymin) == (real)(xmin * ymin)
(float)(xmax * ymax) == (real)(xmax * ymax)
(float)(xmax * ymin) == (real)(xmax * ymin)
number of digits of a + number of digits of b <= 7
number of digits a <= 3    // Number of digits a == number of digits b