Kiedy porównujesz liczby zmiennoprzecinkowe, co nazywasz progiem różnicy?


10

Porównuję teraz zmiennoprzecinkowe w Javie, a najprostszą formułą jest:

Math.abs(a - b) < THRESHOLD

Czy nazywając zmienną próg różnicy, powinieneś nazwać ją delta lub epsilon ? W szczególności, który z dwóch jest poprawnym terminem na najmniejszą wartość, którą może reprezentować liczba zmiennoprzecinkowa?

Czy termin jest specyficzny dla języka programowania, czy jest uniwersalny w różnych językach?


1
Terminy alternatywne: „precyzja”, „rozdzielczość”. Lubię je dokładnie;), ponieważ nie brzmią zbyt technicznie.
stakx

1
Off-topic: Floating-Point zaleca przed zastosowaniem tego typu porównania niemal równości.
stakx

1
@stakx - sugerowane terminy są niepoprawne i mają inne znaczenie niż to, o co prosi OP. Pytanie jest szczegółowo, tak, ale to jest odpowiedzialny oparciu zadawania zewnętrznego i to ma znaczenie dla programowania w kontaktach z wartości zmiennoprzecinkowych. Jest konstruktywny i tematyczny.

1
@ GlenH7: Nigdy nie powiedziałem, że pytanie nie było dobre ani nie można na nie odpowiedzieć. Tak naprawdę to ja głosowałem za tym. A ponieważ twierdzisz, że (co prawda mniej precyzyjne) warunki, które zasugerowałem, są nieprawidłowe, chciałbym dowiedzieć się, dlaczego tak jest.
stakx

@stakx - przeprosiny za sugerowanie, że głosowałeś za zamknięciem. W tej chwili bardziej reagowałem na cztery bliskie głosy w tej sprawie.

Odpowiedzi:


18

Epsilon w matematyce i inżynierii

Z matematyki i inżynierii w ogóle:

  • Delta jest zwykle używana w odniesieniu do różnicy, która może mieć dowolną skalę.
  • Epsilon jest zwykle używany w odniesieniu do niewielkiej ilości.

i epsilon wydaje się bardziej odpowiedni w twoim przypadku.


Epsilon w informatyce

W szczególności w informatyce termin epsilon odnosi się również do espilon maszynowy, który mierzy różnicę między 1.0fnajmniejszym pływakiem, który jest ściśle większy niż 1.0f. Ta ostatnia liczba dotyczy liczb 1.00000011920928955078125fzmiennoprzecinkowych w Javie i można ją obliczyć za pomocą:

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

Definicja maszyny epsilon jest zgodna z ogólnym zastosowaniem epsilon opisanym powyżej.


Porównywanie pływaków

Zauważ jednak, że przed porównaniem pływaków pod kątem „bliskości”, musisz mieć pojęcie o ich skali. Dwa bardzo duże i rzekomo bardzo różne zmiennoprzecinkowe mogą być równe:

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

I odwrotnie, może być wiele możliwych wartości pływaka (i kilka rzędów wielkości) między dwoma małymi pływakami, które różnią się epsilon maszyny „tylko”. W poniższym przykładzie istnieje 10 000 000 dostępnych wartości zmiennoprzecinkowych między smalli f, ale ich różnica jest nadal znacznie poniżej epsilon maszyny:

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!

Artykuł połączony w odpowiedzi GlenH7 bada dalej porównanie zmiennoprzecinkowe i proponuje kilka rozwiązań w celu przezwyciężenia tych problemów.


2
-1: W naukowym oprogramowaniu komputerowym Epsilon odnosi się do epsilon maszynowy lub epsilon względny (patrz ten sam artykuł). Zazwyczaj nie jest to ta sama ilość stosowana w celu przyjęcia przybliżonej równości, ponieważ błędy zaokrąglania są wielokrotnościami epsilonów maszynowych lub względnych epsilonów i zwykle są o kilka rzędów wielkości większe niż to.
rwong,

1
@rwong Jest to jedna ze specjalizacji terminu epsilon i istnieje wiele innych. Ogólnie rzecz biorąc, epsilon odnosi się do małej ilości lub błędu, a epsilon maszynowy jest zgodny z tym pomysłem.
assylias

@assylias, używając nazwy o standardowej definicji, w kontekście, w którym standardowa definicja ma sens, ale dla czegoś, co nie odpowiada standardowej definicji, jest potwierdzenie problemów.
AProgrammer

@AProgrammer Nie zgadzam się, że ogólna definicja epsilon nie ma zastosowania do komputerów.
assylias,

1
@assylias: dzięki za wyjaśnienie. Usunąłem moje -1.
rwong

16

W matematyce delta jest używana do reprezentowania pewnej różnicy od wartości, epsilon jest używany do reprezentowania arbitralnej wartości błędu. W tym przypadku epsilon będzie konwencjonalną nazwą.


8

Aby bezpośrednio odpowiedzieć na twoje pytanie, chcesz użyć tego terminu epsilon. Mówiąc dokładniej, jest to machine epsilonjednak powszechne użycie porzuca „maszynę” i po prostu używa epsilon.

Przeglądając moją lokalną kopię float.h, widzę:

#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 */

A powiązane komentarze wyjaśniają, że epsilon jest terminem, o którym mówisz.

Ale możemy również polegać na innych zewnętrznych odnośnikach, aby sprawdzić, czy epsilonjest to poprawny termin. Zobacz tutaj , tutaj , tutaj , a na koniec ta kombinacja znaczników zapytania SO . Nie byłem w stanie znaleźć bezpośredniego odniesienia do normy IEEE 754.


Nie pytałeś, ale znalazłem to odniesienie, które jest bardzo istotne w podanym przez ciebie przykładzie w celu wyjaśnienia twojego pytania.

Przeczytaj ten artykuł na blogu autorstwa Bruce'a Dawsona z Valve na temat porównywania wartości zmiennoprzecinkowych, aby uzyskać wgląd w to, dlaczego nie chcesz używać sugerowanego porównania.

W tym artykule znajduje się sporo informacji, ale jest to najbardziej odpowiedni fragment:

Jeśli porównywanie liczb zmiennoprzecinkowych pod kątem równości jest złym pomysłem, to co powiesz na sprawdzenie, czy ich różnica mieści się w granicach błędu lub wartości epsilon, na przykład:

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

Dzięki tym obliczeniom możemy wyrazić koncepcję dwóch pływaków na tyle blisko, że chcemy uznać je za równe. Ale jaką wartość powinniśmy zastosować dla epsilon?
Biorąc pod uwagę powyższe eksperymenty, możemy ulec pokusie wykorzystania błędu w naszej sumie, która wynosiła około 1,19e-7f. W rzeczywistości istnieje nawet definicja w float.h z tą dokładną wartością i nazywa się FLT_EPSILON.
Wyraźnie to wszystko. Bogowie plików nagłówkowych mówili, a FLT_EPSILON to jedyny prawdziwy epsilon!
Tyle że to śmieci. Dla liczb od 1,0 do 2,0 FLT_EPSILON reprezentuje różnicę między sąsiednimi zmiennoprzecinkowymi. W przypadku liczb mniejszych niż 1,0 epsilon FLT_EPSILON szybko staje się zbyt duży, a przy wystarczająco małych liczbach FLT_EPSILON może być większy niż liczby, które porównujesz!

Dawson zastanawia się nad kilkoma innymi rozważaniami na temat zawiłości związanych z porównywaniem pływaków i radzeniem sobie z bardzo małymi wartościami takimi jak ta, więc zachęcam do przeczytania reszty jego postu.


Możesz wyjaśnić pierwszą część swojej odpowiedzi: artykuł Bruce'a wyjaśnia już, dlaczego nie należy używać stałego epsilonu (takiego jak te zdefiniowane w pliku nagłówkowym) do porównania tolerancji. Ponadto w wielu przypadkach błąd kilku milionów ULP nie jest powodem do niepokoju, ponieważ w większości aplikacji bardziej zależy nam na cyfrach znaczących niż na błędach cyfr najmniej istotnych, ponieważ podwójna precyzja już daje o wiele więcej cyfr, niż nam zależy.
rwong,

@rwong - kiedy to czytałem, pytanie polegało na zidentyfikowaniu prawidłowego terminu, którego należy użyć dla nazwy stałej. Dlatego właśnie podałem odnośnik do float.h wraz z kilkoma innymi do maszyny epsilon. Artykuł z Dawson jest czymś, co znalazłem podczas wyszukiwania odniesienia do IEEE 754 i uważałem, że jest on odpowiedni do porównania z PO simplest formula. Wiele osób stosuje to podejście jako pierwszą próbę i dołączyłem artykuł Dawsona, ponieważ naprawdę wpada on w niuanse tego, jak trudne jest porównanie. Próbowałem więc bezpośrednio odpowiedzieć na pytanie, a następnie wskazać, dlaczego nie użyć go w ten sposób.

5

To jest funkcja błędu; błąd bezwzględny jest zwykle nazywany ε (epsilon) lub Δ x dla pewnej ilości x:

ε = | oczekiwany - rzeczywisty |

Δ x = | x 0 - x  |

Błąd względny jest czasem nazywany η (eta):

η = | 1 - rzeczywiste / oczekiwane |

Do celów programowania absoluteErrori relativeError(lub niektóre ich skróty) są bardziej opisowe. Jeśli chcesz stwierdzić, że błąd jest mniejszy niż pewna wartość, wartość ta byłaby po prostu nazywana progiem lub tolerancją .

Widzieć:


3

Nazwałbym to „tolerancją”.

Może nie jest to matematycznie poprawny termin, ale sam fakt, że zadajesz pytanie, sugeruje mi, że ani „delta”, ani „epsilon” nie byłyby dobrą nazwą zmiennej zmiennej.

Z mojego doświadczenia wynika, że ​​lepiej jest używać nazw identyfikatorów, które mają sens dla tych, którzy faktycznie czytają kod. Co to za dobrze poprawna nazwa, jeśli oznacza, że ​​czytelnik musi sprawdzić ją w Wikipedii, aby zrozumieć, co to znaczy?


+1. Zawsze mam nadzieję, że ludzie pytają swoich współpracowników o te pytania dotyczące nazewnictwa, a także zamieszczają posty tutaj.
MarkJ

6
-1, Lepiej nauczyć się konwencji niż ich unikać.
djechlin

+1, ponieważ jest to dokładnie ten sam powód, dla którego opublikowałem to pytanie.
NobleUplift,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.