Чи є якісь недоліки використання чеків відстані в квадраті, а не відстані?


29

Я використовую чеки в квадраті відстані для перевірки в основному всієї моєї відстані (vector3 довжина), завдяки збільшенню продуктивності від нестачі квадратного кореня (як, наприклад, у звичайній перевірці довжини).

З огляду на це, квадратні перевірки відстані справно працюють у будь-якій ситуації:

if x^2 < y^2, then x < y, even when 0 < (x or y) < 1

Я не розглядаю ситуації, коли х або у менше 0, оскільки відстань і відстань у квадраті завжди будуть позитивними.

Оскільки це працює, схоже, що дистанційні перевірки ніколи не потрібні, але у мене виникає неприємне відчуття, що я щось пропускаю. Чи все-таки це утримається в критичних ситуаціях?

Відповіді:


41

Немає недоліків, про які я знаю, коли використовую довжину квадрата для порівняння відстаней. Подумайте про це так: Ви просто пропускаєте те, sqrtщо не дає додаткової точності. Якщо вам не потрібна фактична евклідова відстань, ви можете сміливо залишити sqrtпоза.

Звичайно, довжина квадрата масштабується зовсім інакше, ніж евклідова відстань, і тому є поганим кандидатом у таких речах, як евристика прокладання маршрутів .


16
Квадратний корінь фактично знімає точність з перевірки відстані. Ви можете подумати про це як спробу взяти квадратний корінь фіксованого числа в точці між 1 і 2 і зберегти результат (між 1 і sqrt (2)) в абсолютно однаковому діапазоні. Деякі відстані, які порівнюються як x ^ 2 <y ^ 2, порівнюються як x = y після того, як ви візьмете квадратний корінь. Перевірка довжини квадрата є одночасно швидшою та точнішою.
Джон Калсбек

Дякую за відмінні відповіді bummzack та Джон Calsbeek! Ваші відповіді в поєднанні чудово відповідають на моє запитання. Я не вважав додатковий простір пам’яті від того, щоб не використовувати квадратний корінь, дуже приємний пікап там. І що посилання на евристику робить чудовим читання
Aralox

1
За винятком випадку A *. Пригадую, читав статтю, в якій описували тестовані різні евристики та d^2виконували жахливо. В A * |dx| + |dy|прекрасно працює. У мене немає посилання, коли я читав місяць або близько того назад.
Джонатан Дікінсон

3
У випадку A * ви не просто порівнюєте відстані, а додаєте їх, тому пропуск у sqrt має значення.
amitp

1
@bobobobo я згоден; Я в основному змусив збити потенційний аргумент в інший бік, тобто нормальна відстань якось точніше.
Джон Калсбек

14

Як підказки натякають на аналогію пошуку шляху, вам потрібно НЕ використовувати "звичайну" довжину щоразу, коли ви додаєте відстані разом і хочете порівняти їх суму. (Просто тому, що підсумки квадратів довжин відрізняються від квадратних сум довжин).

x ^ 2 + y ^ 2! = (x + y) ^ 2


4

Єдиний недолік, про який я можу подумати, - це мати справу з великою кількістю, яка переповниться, коли буде поставлено квадрат.

Наприклад, на Java:

int x = Integer.MAX_VALUE / 1000000; //2147
int y = Integer.MAX_VALUE / 5000; //429496
System.out.println("x < y: " + (x < y)); //true
System.out.println("x*x: " + (x * x)); //4609609
System.out.println("y*y: " + (y * y)); //-216779712 - overflows!
System.out.println("x*x < y*y: " + (x * x < y * y)); //false - incorrect result due to overflow!

Також варто зазначити, що це відбувається, коли ви використовуєте Math.pow () з точно такими ж номерами і повертаєте до int з подвійного повернутого з Math.pow():

System.out.println("x^2: " + (int) (Math.pow(x, 2))); //4609609
System.out.println("y^2: " + (int) (Math.pow(y, 2))); //2147483647 - double to int conversion clamps to Integer.MAX_VALUE
System.out.println("x^2 < y^2: " + ((int) (Math.pow(x, 2)) < (int) (Math.pow(y, 2)))); //true - but for the wrong reason!

Це працює? Ні , він дав правильну відповідь лише тому y*y, що затискається Integer.MAX_VALUE, і x*xменше, ніж Integer.MAX_VALUE. Якщо вас x*xтакож затискали, Integer.MAX_VALUEви отримаєте неправильну відповідь.

Подібні принципи також застосовуються для плавців та парних пар (за винятком того, що вони, очевидно, мають більший діапазон, перш ніж вони переповнюються) та будь-якої іншої мови, яка мовчки дозволяє переповнення.


Більшість людей використовують floatз для координат, які тільки переповнення після про 10^38НЕ int.
bobobobo

Але в 10 ^ 38 ви втратили настільки точність, що насправді не можете бути впевнені, що ваші порівняння на відстані вже дійсні - переповнення не єдина проблема тут. Див. Altdevblogaday.com/2012/02/05/dont-store-that-in-a-float (розділ "Таблиці" підсумовує втрати на точність до 1 мільярда).
Максим Мінімус

У вас буде однакова проблема переповнення з sqrt (x * x). Я не бачу вашої суті. Йдеться не про Манхеттенську відстань тощо
bogglez

@bogglez - залежить від того, збільшиться чи ні, щоб ваша бібліотека (або процесор) збільшилась удвічі чи ні.
Максим Мінімус

3

Один раз я працював на квадратних відстанях і робив помилку накопичуючи відстані в квадраті, для підрахунку одометра.

Звичайно, ви не можете цього зробити, тому що математично,

(a^2+b^2+c^2+d^2)!=(a+b+c+d)^2

Отже, я закінчився там неправильним результатом. На жаль!


1
Крім того, я можу додати, що було декілька разів, коли я намагався використовувати відстані в квадраті, тільки для того, щоб виявити мені потрібні фактичні відстані пізніше в тій же гілці коду. Отже, не перестарайтеся. Іноді не варто дотримуватися незручності зберігати квадратичні коефіцієнти скрізь, коли вам потрібно все- sqrtтаки зробити операцію.
бобобобо

3

У вас можуть виникнути проблеми, якщо ви пишете алгоритм, який вимагає обчислити оптимізовану позицію. Наприклад, скажімо, у вас був набір об'єктів, і ви намагалися обчислити позицію з найменшою загальною відстані від усіх об'єктів. Для конкретного прикладу, скажімо, ми намагаємось живити три будівлі, і ми хочемо зрозуміти, куди повинна йти електростанція, щоб ми могли підключити її до всіх будівель, використовуючи найменшу загальну довжину проводу. Використовуючи метрику відстані в квадраті, ви закінчите, щоб координата x електростанції була середнім значенням x-координат усіх будівель (і аналогічно y-координаті). Використовуючи звичайну метрику відстані, рішення було б іншим і часто дуже далеким від рішення відстані у квадраті.


Здається, можна сперечатися, що було б краще чи гірше для даної ситуації. Я пам'ятаю, що математики часто обирають використовувати відстань у квадраті під час встановлення лінії до набору точок. Можливо, вони роблять це, тому що це зменшує вплив самотніх людей. У вашому випадку з трьома будівлями, чужі люди не можуть становити ризик. Або, можливо, вони це роблять, тому що з ними x^2легше працювати |x|.
joeytwiddle

@joeytwiddle Надзвичайники фактично впливають на лінійну регресію більше з розмірами найменших квадратів, ніж абсолютна відстань. Ви маєте рацію, що це використовується, тому що з ним легше працювати. У прикладі, який я наводив (навіть якщо він модифікований, щоб містити велику кількість будівель), метрика квадрата відстані розв’язується за допомогою простої формули (середнє арифметичне кожної координати), але показник абсолютної відстані є математично незмінним і повинен бути вирішено приблизно за допомогою одного з ряду числових методів.
Олександр Грубер

Дякуємо за виправлення. Звичайно, ви маєте рацію, квадрат відстані генерує більшу помилку для людей, що втрачають силу, збільшуючи їх вплив, а не зменшуючи її, як я неправильно зазначив вище. Це захоплююче, наскільки складніше вирішити найменш абсолютну відстань.
joeytwiddle

0

Використання відстані в квадраті майже завжди добре і добре для продуктивності. Наступні міркування важливі:

Якщо ви хочете подумати про суму ряду відстаней, відстань у квадраті буде неточною. Наприклад, у мене дві відстані, і я хочу переконатися, що їх сума менше 10. Наступний код невірний:

a = get_distance_squared(c,d);
b = get_distance_squared(e,f);
assert(a+b < 10^2);

Він не може стверджувати у такій недійсній справі: a=36та b=49. У цьому випадку перша довжина дорівнює 6, а друга 7; їх сума більша за 10, але сума квадратів не 100 і більше.

Ще одне враження: для реальних цінностей відстань у квадраті завжди буде позитивною. Якщо, наприклад, ви вимірюєте переміщення, вам, можливо, доведеться мати справу з негативними значеннями, і розбір їх не зробить.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.