Dlaczego wartość Double.MIN_VALUE nie jest liczbą ujemną

157

Czy ktoś może rzucić trochę światła na to, dlaczego Double.MIN_VALUE to, rzeczywistości nie jest to minimalna wartość, jaką może przyjąć Doubles? Jest to wartość dodatnia, a Double może oczywiście być ujemne.

Rozumiem, dlaczego jest to przydatna liczba, ale wydaje się bardzo nieintuicyjna nazwa, zwłaszcza w porównaniu z Integer.MIN_VALUE. Nazywanie go Double.SMALLEST_POSITIVElub MIN_INCREMENTpodobnie miałoby jaśniejszą semantykę.

Jaka jest minimalna wartość, jaką może przyjąć dublet? Czy to jest -Double.MAX_VALUE? Doktorzy nie wydają się mówić.

mo-seph
źródło
1
Dzięki za odpowiedzi! Różnica między zasięgiem a precyzją ma sens. Nadal uważam nazewnictwo za dość dziwne i niespójne, ale działa.
mo-seph,
1
Zgaduję, ponieważ został napisany przez tych samych geniuszy, którzy nazwali metodę, writeBytesktóra przyjmuje String.
Trejkaz
Zasadniczo masz rację, to zła semantyka
Alvaro,

Odpowiedzi:

180

Format IEEE 754 ma jeden bit zarezerwowany dla znaku, a pozostałe bity reprezentują wielkość. Oznacza to, że jest „symetryczny” wokół origo (w przeciwieństwie do wartości całkowitych, które mają jeszcze jedną wartość ujemną). Zatem minimalna wartość jest po prostu taka sama jak maksymalna, ze zmienionym bitem znaku, więc tak , -Double.MAX_VALUEjest najmniejszą możliwą rzeczywistą liczbą, którą można przedstawić za pomocądouble .

Przypuszczam, że Double.MAX_VALUEpowinno być postrzegane jako wielkość maksymalna , w takim przypadku po prostu napisanie ma sens -Double.MAX_VALUE. Wyjaśnia również, dlaczegoDouble.MIN_VALUE jest najmniej dodatnią wartością (ponieważ reprezentuje najmniejszą możliwą wielkość).

Ale jasne, zgadzam się, że nazewnictwo jest nieco mylące. Przywykłem do tego znaczenia Integer.MIN_VALUEi byłem nieco zaskoczony, gdy przeczytałem, że Double.MIN_VALUEjest to najmniejsza wartość bezwzględna, jaką można przedstawić. Być może uważali, że zbyteczne jest posiadanie stałej reprezentującej najmniejszą możliwą wartość, ponieważ jest po prostu -oddalonaMAX_VALUE :-)

(Uwaga, jest też Double.NEGATIVE_INFINITY ale pomijam to, ponieważ należy to postrzegać jako „przypadek specjalny” i nie reprezentuje żadnej rzeczywistej liczby).

Oto dobry tekst na ten temat.

aioobe
źródło
3
Dzięki za to. Portowałem kod analizy statystycznej i ślepo tłumaczyłem Javę na C #. Zauważyłem kilka liczb wychodzących na -infinity lub NaN i przyjrzałem się algorytmowi. Zdałem sobie sprawę, że to double.MIN_VALUE nie ma sensu w kontekście i przeprowadziłem wyszukiwanie. Ten post pojawia się przed dokumentacją java. To naprawdę myląca nazwa tego, co naprawdę jest podwójne - epsilon. Nic wielkiego, naprawienie go zajęło mniej niż minutę, ale zdecydowanie zaskakujące.
Ed S.,
Czy „najmniejsza wartość bezwzględna, którą można przedstawić” nie powinna nosić nazwy „epsilon”?
Dave Cousineau
@Sahuagin, tak naprawdę nie należy nazywać niczego szczególnego. Epsilon to po prostu grecka litera, która zwykle reprezentuje arbitralnie małą wartość dodatnią w matematyce / fizyce. SmallestNonzeroFloat64Na przykład wybierz .
aioobe
12

Te stałe nie mają nic wspólnego ze znakiem. Ma to większy sens, jeśli weźmiesz pod uwagę podwójną jako złożenie trzech części: znaku, wykładnika i mantysy. Double.MIN_VALUE jest w rzeczywistości najmniejszą wartością, jaką mantysa może przyjąć, gdy wykładnik ma wartość minimalną, zanim nastąpi wyrównanie do zera. Podobnie MAX_VALUE można rozumieć jako największą wartość, jaką mantysa może przyjąć, gdy wykładnik ma maksymalną wartość, zanim nastąpi wyrównanie do nieskończoności.

Bardziej opisową nazwą dla tych dwóch może być Największy Bezwzględny (dodaj wartość niezerową dla dosłowności) i Najmniejsza wartość bezwzględna (dodaj wartość niezerową dla dosłowności).

Sprawdź IEEE 754 (1985) . Istnieje poprawiona wersja (2008), ale wprowadza ona tylko więcej formatów, które nie są nawet obsługiwane przez Javę (ściśle mówiąc, java nawet nie obsługuje niektórych obowiązkowych funkcji IEEE 754 1985, podobnie jak wiele innych języków wysokiego poziomu).

Durandal
źródło
4

Zakładam, że mylące nazwy można prześledzić wstecz do C , które zdefiniowałoFLT_MIN jako najmniejszą liczbę dodatnią.

Podobnie jak w Javie, gdzie musisz użyć -Double.MAX_VALUE, musisz użyć, -FLT_MAXaby uzyskać najmniejszy float w C.

Philipp Claßen
źródło
3

Minimalna wartość dla double jest Double.NEGATIVE_INFINITYtaka, dlaczego Double.MIN_VALUEtak naprawdę nie jest minimalna dla aDouble .

Ponieważ podwójne są liczbami zmiennoprzecinkowymi, możesz mieć tylko największą liczbę (z mniejszą dokładnością) lub liczbę najbliższą 0 (z dużą dokładnością).

Jeśli naprawdę chcesz mieć minimalną wartość podwójnej wartości, która nie jest nieskończonością, możesz użyć -Double.MAX_VALUE.

Colin Hebert
źródło
1
Zgodnie z tym pomysłem, czy maksymalna wartość Double Double.MAX_VALUE czy Double.POSITIVE_INFINITY?
mo-seph,
Double.MIN_VALUEmoże być równe Double.NEGATIVE_INFINITY.
starblue
@starblue, nie. @ mo-seph,, Double.POSITIVE_INFINITY+ ∞> wszystko i —∞ <wszystko
Colin Hebert,
@Colin Hebert,> = i <= by być precyzyjnym ;-)
aioobe
Prawdopodobnie źle mnie zrozumiałeś. W lepszym świecie Double.MIN_VALUEbyłaby równa Double.NEGATIVE_INFINITY, bo wtedy byłaby zgodna z MIN_VALUEtypami całkowitymi. Mógłbym zainicjować dowolną zmienną do obliczenia maksimum z MIN_VALUEi byłoby to poprawne. Double.MIN_VALUEMamy teraz miałaby lepszą nazwę. (I analogicznie do MAX_VALUE.)
starblue
2

Ponieważ w przypadku liczb zmiennoprzecinkowych dokładność jest ważna, ponieważ nie ma dokładnego zakresu .

/**
 * A constant holding the smallest positive nonzero value of type
 * <code>double</code>, 2<sup>-1074</sup>. It is equal to the
 * hexadecimal floating-point literal
 * <code>0x0.0000000000001P-1022</code> and also equal to
 * <code>Double.longBitsToDouble(0x1L)</code>.
 */

Ale zgadzam się, że prawdopodobnie należało to nazwać lepiej :)

John Gardner
źródło
OK, ale w takim razie dlaczego warto mieć Double.MAX_VALUE? Wydaje się, że jest to jasno określone.
mo-seph,
ponieważ jest to maksymalna dokładna wartość (nie nieskończona), bez uwzględnienia jej znaku.
John Gardner
0

Jak jest napisane w dokumentach ,

Double.MIN_VALUE jest stałą przechowującą najmniejszą DODATNI niezerową wartość typu double, 2 ^ (- 1074).

Sztuczka polega na tym, że mówimy o reprezentacji liczb zmiennoprzecinkowych. Typ danych double to 64-bitowy zmiennoprzecinkowy podwójnej precyzji IEEE 754. Punkty zmiennoprzecinkowe z łatwością reprezentują liczby od 1000000000000 do 0,0000000000000001 , jednocześnie maksymalizując precyzję (liczbę cyfr) na obu końcach skali. (Aby uzyskać więcej informacji, odnieś się do tego )

Mantysa, zawsze liczbą dodatnią , posiada znaczące cyfry numeru zmiennoprzecinkowej. Wykładnik wskazuje dodatnią lub ujemną moc podstawy, przez którą należy pomnożyć mantysę i znak. Cztery składniki są połączone w następujący sposób, aby uzyskać wartość zmiennoprzecinkową.

wprowadź opis obrazu tutaj

Pomyśl, że MIN_VALUE to minimalna wartość, jaką może reprezentować mantysa. Jako minimalne wartości reprezentacji zmiennoprzecinkowej jest minimalna wielkość, którą można przedstawić za pomocą tego. (Mogłem użyć lepszej nazwy, aby uniknąć tego zamieszania)

123> 10> 1> 0,12> 0,012> 0,0000123> 0,000000001> 0,0000000000000001


Poniżej znajduje się tylko FYI.

Zmiennoprzecinkowe podwójnej precyzji mogą reprezentować 2098 potęgi dwóch, od 2 ^ -1074 do 2 ^ 1023. Zdenormalizowane potęgi dwójki to te od 2 ^ -1074 do 2 ^ -1023; znormalizowane potęgi dwójki to te od 2 ^ -1022 do 2 ^ 1023. Odnieś się do tego i tego .

główny
źródło
Dziękuję Ci! Nie wiem, dlaczego ta odpowiedź została odrzucona.
Połącz