Порівнюючи поплавці, як ви називаєте поріг різниці?


10

Зараз я порівнюю поплавці на Java і найпростіша формула:

Math.abs(a - b) < THRESHOLD

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

Чи є термін мовою програмування специфічним чи він універсальним для різних мов?


1
Альтернативні терміни: "точність", "роздільна здатність". Мені це подобається саме;), оскільки вони не звучать надто технічно.
stakx

1
Поза темою: Посібник з плаваючою комою рекомендує не використовувати цей тип порівняння майже рівності.
stakx

1
@stakx - терміни, які ви пропонуєте, невірні та мають різний зміст від того, про що питає ОП. Питання докладно, так, але це відповідальність грунтується на зовнішні посилання і він має відношення до програмування при роботі зі значеннями з плаваючою точкою. Це конструктивно і тематично.

1
@ GlenH7: Я ніколи не говорив, що це питання не є гарним або не відповідає. Насправді я був тим, хто виступав проти цього. А оскільки ви стверджуєте, що (правда, менш точні) умови, які я запропонував, є невірними, мені було б цікаво дізнатись, чому це так.
stakx

@stakx - вибачення за те, що ви сказали, що ви проголосували за закриття. На даний момент я реагував більше на чотири закритих голоси.

Відповіді:


18

Епсілон з математики та техніки

У математиці та техніці взагалі:

  • Дельта зазвичай використовується для позначення різниці, яка може бути будь-якого масштабу.
  • Епсилон зазвичай використовується для позначення незначної кількості.

і епсилон здається більш відповідним у вашому випадку.


Епсилон з інформатики

Зокрема, в інформатиці термін epsilon також відноситься до машинного еспілону, який вимірює різницю між 1.0fнайменшим поплавком, який суворо більший за 1.0f. Останнє число призначено 1.00000011920928955078125fдля плавців на Java і може бути обчислено за допомогою:

float f = Float.intBitsToFloat(Float.floatToIntBits(1f) + 1);

Визначення машинного епсилона відповідає загальному використанню епсилону, описаному вище.


Порівнюючи поплавці

Однак зауважте, що перш ніж порівнювати поплавці для "близькості", ви повинні мати уявлення про їх масштаб. Два дуже великих і нібито дуже різних поплавця можуть бути рівними:

9223372036854775808f == 9223372036854775808f + 1000000000f; //this is true!

І навпаки, може бути багато можливих значень поплавків (і декількох порядків) між двома маленькими поплавцями, які відрізняються машинним епсилоном "тільки". У наведеному нижче прикладі є 10000000 доступних значень плавучих значень між smallта f, але їх різниця все ще значно нижче машинного епсилону:

float small = Float.MIN_VALUE; // small = 1.4E-45
float f = Float.intBitsToFloat(Float.floatToIntBits(small) + 100000000); // f = 2.3122343E-35
boolean b = (f - small < 0.00000011920928955078125f); //true!

У статті, зв'язаній у відповіді GlenH7, далі досліджується порівняння з поплавцем та пропонується кілька рішень для подолання цих питань.


2
-1: У науковому обчислювальному програмному забезпеченні Epsilon посилається на машинний епсилон або на відносний епсилон (див. Ту саму статтю). Зазвичай це не та сама величина, яка використовується для прийняття наближеної рівності, оскільки помилки округлення є кратними машинними епілонами або відносними епілонами, і, як правило, на кілька порядків більше, ніж це.
rwong

1
@rwong Це одна спеціалізація терміна epsilon , а є багато інших. В інженерії взагалі epsilon посилається на невелику кількість або помилку, і Machine epsilon сумісний з цією ідеєю.
assylias

@assylias, використовуючи ім'я, яке має стандартне визначення, в контексті, коли стандартне визначення має сенс, але для чогось, що не відповідає стандартному визначенню, є квитанцією про проблеми.
AProgrammer

@AProgrammer Я не погоджуюся, що загальне визначення epsilon не застосовується до обчислень.
assylias

1
@assylias: дякую за роз’яснення. Я прибрав -1.
rwong

16

У математиці дельта використовується для представлення деякої різниці від значення, epsilon використовується для подання довільного значення помилки. У цьому випадку епсилон був би умовною назвою.


8

Щоб безпосередньо відповісти на ваше запитання, ви хочете використовувати термін epsilon. Точніше, machine epsilonале звичайне використання падає «машина» та просто використовує epsilon.

Заглядаючи в свою місцеву копію, float.hя бачу:

#define DBL_EPSILON     2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */  
#define FLT_EPSILON     1.192092896e-07F        /* smallest such that 1.0+FLT_EPSILON != 1.0 */  
#define LDBL_EPSILON    DBL_EPSILON             /* smallest such that 1.0+LDBL_EPSILON != 1.0 */

І пов'язані з цим коментарі дають зрозуміти, що epsilon - це термін, про який ви посилаєтесь.

Але ми можемо також покластись на деякі інші зовнішні посилання, щоб переконатися, що epsilonце правильний термін. Дивіться тут , тут , тут , і нарешті це поєднання тегів запитів SO . Я не зміг знайти пряму посилання на стандарт IEEE 754, який я наводив.


Ви не запитували, але я знайшов цю посилання дуже важливою для прикладу, який ви надали для уточнення свого питання.

Погляньте на цю статтю Блога Брюса Доусона з Valve про порівняння значень з плаваючою комою для деякого розуміння того, чому ви не хочете використовувати порівняння, яке ви запропонували.

У цю статтю запаковано досить багато інформації, але це найвідповідніший фрагмент звідти:

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

bool isEqual = fabs(f1 – f2) <= epsilon;

Цим розрахунком ми можемо виразити, що два поплавця є досить близькими, що ми хочемо вважати їх рівними. Але яке значення ми повинні використовувати для epsilon?
Враховуючи наші експерименти вище, ми можемо спокуситись використовувати помилку в нашій сумі, яка була приблизно 1,19e-7f. Насправді в float.h є навіть визначення з таким точним значенням, і воно називається FLT_EPSILON.
Ясно, що це все. Боги заголовкового файлу говорили, і FLT_EPSILON - це єдиний справжній епсилон!
Крім того, що це сміття. Для чисел від 1,0 до 2,0 FLT_EPSILON являє собою різницю між суміжними поплавками. Для чисел, менших ніж 1,0, епсилон FLT_EPSILON швидко стає занадто великим, а при достатньо малих числах FLT_EPSILON може бути більшим, ніж числа, які ви порівнюєте!

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


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

@rwong - коли я читав, питання полягало в тому, щоб визначити правильний термін, який слід використовувати для імені константи. Отож, тому я надав посилання float.h разом з кількома іншими на машину epsilon. Стаття від Доусона - це те, що я знайшов під час пошуку посилання на IEEE 754, і я вважав, що стосується ОП simplest formulaдля порівняння. Багато хто використовує цей підхід як першу спробу, і я включив статтю Доусона, оскільки він дійсно входить у нюанси того, наскільки складним є порівняння. Тож я спробував безпосередньо відповісти на питання, а потім вказати, чому б не використовувати його таким чином.

5

Це функція помилок; абсолютну похибку зазвичай називають ε (epsilon) або Δ x для деякої кількості x:

ε = | очікуване - фактичне |

Δ x = | x 0 - x  |

Відносну помилку іноді називають η (eta):

η = | 1 - фактичний / очікуваний |

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

Подивитися:


3

Я б назвав це "толерантністю".

Можливо, це не математично правильний термін, але сам факт, що ви задаєте запитання, означає, що ні "дельта", ні "епсілон" не були б хорошим ім'ям змінної.

На мій досвід, краще використовувати імена ідентифікаторів, що має сенс для тих, хто насправді прочитає код. Що корисного - це цілком правильне ім’я, якщо воно означає, що читачеві потрібно шукати його у Вікіпедії, щоб зрозуміти, що це означає?


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

6
-1, краще вчитися умовам, ніж уникати їх.
djechlin

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