在交叉产品操作之后精确地比较浮子

时间:2015-11-15 07:48:04

标签: math floating-point integer geometry precision

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

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

问题定义

给定由以下等式描述的一组网格点

P(x, y) = P(i, j) * delta = P(i * delta,  j * delta)

其中0 <= i&lt;分辨率,0&lt; = j&lt;分辨率,delta = size /(resolution -1)

给定任意3个不同点P0,P1和P2的组合,需要为表达式获得准确的布尔值:

CrossProduct(P1 - P0, P2 - P0) < 0

CrossProduct(P1 - P0, P2 - P0) > 0

CrossProduct(P1 - P0, P2 - P0) == 0

哪里

CrossProduct(lhs, rhs) = lhs.x * rhs.y - lhs.y * rhs.x

整数解决方案

如果我们使用整数来描述点,只要没有溢出就可以使用整数数学来精确计算这些表达式。

P = (i, j)

由于i和j都是&gt; = 0,| i1 - i0 | &LT;因此,CrossProduct将始终具有两个坐标不大于分辨率的参数。所以,没有溢出:

a * b - c * d <= int.MaxValue

其中| a |,| b |,| c |,| d | &LT;分辨率

为无溢出提供以下最大分辨率:

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

使用整数可以完美地工作。唯一的缺点是,点被存储为整数P(i,j),并且每次需要访问实际点值时,需要使用初始公式来获得该点的浮点值P(x) ,y)

问题

是否可以使用浮点数而不是整数来实现此目的?怎么样?

2 个答案:

答案 0 :(得分:0)

这是可能的,但并不容易。本文讨论计算几何的谓词 https://www.cs.cmu.edu/~quake/robust.html

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

答案 1 :(得分:0)

浮动存储mantissas有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个尾数位,其中很大一部分必须是噪声。然后检查有效位的实际数量是有意义的。你会发现你有足够的......花车。