Когда вы сравниваете поплавки, что вы называете порогом разницы?


10

Я сравниваю float в Java прямо сейчас, и самая простая формула:

Math.abs(a - b) < THRESHOLD

Когда вы называете свою переменную для порога разницы, вы должны назвать ее дельтой или эпсилоном ? В частности, какой из двух является правильным термином для наименьшего значения, которое может представлять число с плавающей запятой?

Является ли термин язык программирования конкретным или он универсален для разных языков?


1
Альтернативные термины: «точность», «разрешение». Мне это точно нравится;) потому что они не кажутся слишком техническими.
Stakx

1
Не по теме: вещественное Руководство рекомендует против использования этого типа сравнения вблизи равенства.
stakx

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

1
@ GlenH7: я никогда не говорил, что вопрос не был хорошим или не отвечал. Фактически, я был тем, кто проголосовал за это. И поскольку вы утверждаете, что (предположительно менее точные) термины, которые я предложил, неверны, мне было бы интересно узнать, почему это так.
stakx

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

Ответы:


18

Эпсилон в математике и технике

В математике и технике в целом:

  • Дельта обычно используется для обозначения разницы, которая может быть любого масштаба.
  • Эпсилон обычно используется для обозначения незначительного количества.

и эпсилон кажется более подходящим в вашем случае.


Эпсилон в информатике

В частности, в информатике термин эпсилон также относится к машинному шпилону, который измеряет разницу между 1.0fнаименьшим поплавком, который строго больше, чем 1.0f. Это последнее число 1.00000011920928955078125fдля чисел с плавающей точкой в ​​Java и может быть вычислено с помощью:

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

Определение эпсилон-машины соответствует общему использованию эпсилона, описанному выше.


Сравнение поплавков

Однако обратите внимание, что перед тем, как сравнивать поплавки по «близости», вам необходимо иметь представление об их масштабе. Два очень больших и предположительно очень разных поплавка могут быть равны:

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

И наоборот, может быть много возможных значений поплавка (и нескольких порядков величины) между двумя небольшими поплавками, которые отличаются "только" машинным эпсилоном. В приведенном ниже примере есть 10 000 000 доступных значений с плавающей запятой между 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: В научных вычислительных программах Эпсилон относится либо к Эпсилону машины, либо к Относительному эпсилону (см. Ту же статью). Как правило, это не то же самое количество, которое используется для принятия приблизительного равенства, потому что ошибки округления являются кратными машинных эпсилонов или относительных эпсилонов, и обычно на несколько порядков больше, чем это.
Rwong

1
@rwong Это одна специализация термина epsilon , и есть много других. В целом, в инженерии эпсилон ссылается на небольшое количество или ошибку, и машинный эпсилон совместим с этой идеей.
assylias

@assylias, используя имя, которое имеет стандартное определение, в контексте, где стандартное определение имеет смысл, но для чего-то, что не соответствует стандартному определению, является квитанцией о проблемах.
AProgrammer

@AProgrammer Я не согласен с тем, что общее определение эпсилона не применимо к вычислениям.
assylias

1
@assylias: спасибо за разъяснения. Я удалил свой -1.
Rwong

16

В математике дельта используется для представления некоторого отличия от значения, эпсилон используется для представления произвольного значения ошибки. В этом случае эпсилон будет условным названием.


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это правильный термин. Смотрите здесь , здесь , здесь , и, наконец, эту комбинацию SO запросов тегов . Я не смог найти прямую ссылку на стандарт IEEE 754 для цитирования.


Вы не спрашивали, но я нашел эту ссылку, которая очень подходит к приведенному вами примеру, чтобы прояснить ваш вопрос.

Посмотрите на эту статью в блоге Брюса Доусона из Valve о сравнении значений с плавающей запятой, чтобы понять, почему вы не хотите использовать предложенное сравнение.

В эту статью упаковано довольно много информации, но это самый важный фрагмент:

Если сравнивать поплавки на равенство - плохая идея, то как насчет проверки, находится ли их различие в пределах границ ошибки или значения epsilon, например:

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

С помощью этого расчета мы можем выразить концепцию двух поплавков, находящихся достаточно близко, чтобы мы хотели считать их равными. Но какое значение мы должны использовать для эпсилон?
Учитывая наши эксперименты, приведенные выше, у нас может возникнуть соблазн использовать ошибку в нашей сумме, которая составляла около 1,19e-7f. Фактически, в float.h есть даже определение с этим точным значением, и оно называется FLT_EPSILON.
Понятно, что это так. Боги заголовочного файла говорили, и FLT_EPSILON - единственный настоящий эпсилон!
За исключением того, что это мусор. Для чисел от 1.0 до 2.0 FLT_EPSILON представляет разницу между соседними числами. Для чисел меньше 1,0 эпсилон FLT_EPSILON быстро становится слишком большим, а при достаточно малых числах FLT_EPSILON может быть больше, чем сравниваемые вами числа!

Доусон приводит несколько других соображений о тонкостях, связанных с сравнением чисел с плавающей запятой и с такими очень маленькими значениями, поэтому я бы посоветовал вам прочесть остальную часть его поста.


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

@ rwong - когда я читал это, вопрос заключался в том, чтобы определить правильный термин для использования в качестве имени константы. Вот почему я предоставил ссылку на float.h вместе с несколькими другими на машинный эпсилон. Статья от Доусона - это то, что я нашел, когда искал ссылку на IEEE 754, и я подумал, что она имеет отношение к ОП simplest formulaдля сравнения. Многие используют этот подход в качестве первой попытки, и я включил статью Доусона, потому что она действительно отражает нюансы того, насколько сложным является сравнение. Поэтому я попытался прямо ответить на вопрос, а затем указать, почему бы не использовать его таким образом.

5

Это функция ошибки; абсолютная погрешность обычно называют ε (эпсилон) или Δ х для некоторой величины х:

ε = | ожидаемый - фактический |

Δ х = | х 0 - х  |

Относительную погрешность иногда называют η (эта):

η = | 1 - фактический / ожидаемый |

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

Видеть:


3

Я бы назвал это «толерантностью».

Возможно, это не математически правильный термин, но сам факт того, что вы задаете вопрос, подразумевает для меня, что ни «delta», ни «epsilon» не будут подходящим именем переменной для использования.

По моему опыту, лучше использовать имена идентификаторов, которые имеют смысл для тех, кто действительно читает код. Что хорошего в совершенно правильном имени, если оно означает, что читатель должен найти его в Википедии, чтобы понять, что это значит?


+1. Я всегда надеюсь, что люди спрашивают своих коллег об этих вопросах именования, а также размещают здесь сообщения.
MarkJ

6
-1, лучше изучать условности, чем избегать их.
Джехлин,

+1, потому что это та же самая причина, по которой я разместил этот вопрос.
NobleUplift
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.