【发布时间】:2016-08-21 03:11:08
【问题描述】:
问题定义
我有一个由一组点 (x,y) 表示的二维场景,其中 x 和 y 是 64 位整数。 x 和 y 值都在 [0, R] 的范围内(可能的 x 最小值为 0,最大值为 R。同样的规则适用于 y)。
在我的代码中的某个时刻,我执行以下操作。
// Returns true if point P is inside circle defined by points A, B, C.
private bool InCircle(Long2 A, Long2 B, Long2 C, Long2 P)
{
Long2 AP = P - A;
Long2 BP = P - B;
Long2 CP = P - C;
return AP.SquareMagnitude * Long2.Det(BP, CP) + BP.SquareMagnitude * Long2.Det(CP, AP) + CP.SquareMagnitude * Long2.Det(AP, BP) > 0;
}
// Notes:
SquareMagnitude = x * x + y * y
Long2.Det(a, b) = a.x * b.y - a.y * b.x
我不希望这个操作失败,所以其中的整数不能溢出。最大值出现在以下情况:
- A = (0, 0)
- B = (R, 0)
- C = (0, R)
- P = (R, R)
这些点导致:
- AP = (R, R)
- BP = (0, R)
- CP = (R, 0)
如果这些值在方法上运行,我们得到:
- AP.SquareMagnitude = R² + R²
- Long2.Det(BP, CP) = R²
- BP.SquareMagnitude = R²
- Long2.Det(CP, AP) = R²
- CP.SquareMagnitude = R²
- Long2.Det(AP, BP) = R²
结果变成:
- (2 * R² * R²) + (R² * R²) + (R² * R²) > 0
等同于:
- 4 * (R^4) > 0
如果我们不希望 64 位整数溢出,那么:
- 4 * (R^4)
因此,最大 R 值为 2^15 = 32768。(实际上是 2^15.25,但我们会将其四舍五入为 2^15)。
问题
有什么方法可以增加最大 R 值而不会使用 64 位整数溢出?比如把方程分解成更小的值,然后分别比较。
到目前为止我的想法
我想把等式改成:
return AP.SquareMagnitude * Long2.Det(BP, CP) > -BP.SquareMagnitude * Long2.Det(CP, AP) - CP.SquareMagnitude * Long2.Det(AP, BP);
这会导致:
- 2 * R² * R² > -(R² * R²) - (R² * R²)
- 2 * (R^4)
- R
此外,我不知道这样做是否安全。是吗?
使用整数是有目的的,输出精度是必须的。
我知道这个库:
https://www.cs.cmu.edu/~quake/robust.html
但我想使用整数,而不是浮点数。这里使用的方法在整数溢出限制内是稳健的。只希望扩展此溢出限制。
【问题讨论】:
标签: integer overflow long-integer biginteger integer-overflow