Определение проблемы
У меня есть двухмерный сценарий, представленный набором точек (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) <= (2^63)
Таким образом, максимальное значение 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) <= 2^63
- R ‹ = 2 ^ 15,5 (которое все еще округляется до 2 ^ 15. Недостаточно хорошо)
Кроме того, я не знаю, безопасно ли это делать. Это?
Предполагается использование целых чисел, и точность вывода является обязательной.
Я знаю об этой библиотеке:
https://www.cs.cmu.edu/~quake/robust.html< /а>
Но я хочу использовать целые числа, а не числа с плавающей запятой. Используемый здесь метод устойчив к ограничению переполнения целых чисел. Желательно только расширить это ограничение переполнения.