Вычисления с плавающей точкой и неравенство треугольника
Я использую VPTree для оптимизации некоторых алгоритмов K-ближайших соседей.
VPTree требует, чтобы функция расстояния удовлетворяла неравенству треугольника.
Неравенство треугольника утверждает, что должно быть верно следующее:
distance(x,z) <= distance(x,y) + distance(y,z)
Одной из функций, используемых в нашей функции расстояния, является географическое расстояние в метрах, которое рассчитывается с помощью арифметики с плавающей запятой. Я обнаружил, что эта функция нарушает неравенство треугольника из-за неточных вычислений с плавающей запятой.
Например:
x = -90,-180
y = -90,-162
z = -81,-144
distance(x,z) = 1005162.6564502382
distance(x,y) = 1.2219041408558764E-10
distance(y,z) = 1005162.656450238
distance(x,y) + distance(y,z) = 1005162.6564502381
Очевидно, что неравенство треугольника в этом случае провалилось.
Я возился и обнаружил, что если я округлю расстояние в метрах ВНИЗ до следующего целого числа, то есть Math.floor() в java, а затем добавлю 5, результат, похоже, неожиданно удовлетворит неравенство треугольника во всех случаях. проверил.
Я проверил каждую комбинацию широта / долгота, которая кратна 10, то есть 20^6 комбинаций.
После этого изменения мы получаем следующие результаты для примера выше:
x = -90,-180
y = -90,-162
z = -81,-144
distance(x,z) = 1005167
distance(x,y) = 5
distance(y,z) = 1005167
distance(x,y) + distance(y,z) = 1005172
Очевидно, что в этом случае неравенство треугольника больше не нарушается.
Это кажется идеальным, поскольку 5 метров в нашем случае не имеют значения.
Я просто "заставляю" это работать, и все еще нарушаю какое-то требование неравенства треугольника или некоторое требование VPTrees? Это то, что является известным свойством поплавков?
Обратите внимание, что простое округление ВНИЗ без добавления 5 не работает.
Например:
x = -90,-180
y = -81,-180
z = -72,-180
distance(x,z) = 2009836.0
distance(x,y) = 1005162.0
distance(y,z) = 1004673.0
distance(x,y) + distance(y,z) = 2009835.0
И добавив 5:
x = -90,-180
y = -81,-180
z = -72,-180
distance(x,z) = 2009841.0
distance(x,y) = 1005167.0
distance(y,z) = 1004678.0
distance(x,y) + distance(y,z) = 2009845.0
Также обратите внимание, что я обнаружил, что это работает для любого вида арифметики с плавающей запятой, а не только для географического расстояния. Например, функция расстояния, которая вычисляет процент от некоторого максимального значения с помощью одной операции деления, при условии, что вы всегда округляете до определенного числа цифр и добавляете 5 к последней цифре.
0 ответов
Старая ветка, но не могу удержаться от ответа.
Ваш метод округления в меньшую сторону и добавления пяти может удовлетворять неравенству треугольника, но при этом расстояние между точкой и самой собой будет больше нуля. Что означает, что:
Расстояние (x, x) == 5
ИМО, это, вероятно, так же проблематично для VPTree, чем отказ от свойства неравенства треугольника.