Czy istnieje standardowy i / lub przenośny sposób reprezentowania najmniejszej wartości ujemnej (np. Użycie ujemnej nieskończoności) w programie C (++)?
DBL_MIN w float.h to najmniejsza liczba dodatnia .
Czy istnieje standardowy i / lub przenośny sposób reprezentowania najmniejszej wartości ujemnej (np. Użycie ujemnej nieskończoności) w programie C (++)?
DBL_MIN w float.h to najmniejsza liczba dodatnia .
Odpowiedzi:
-DBL_MAX
w ANSI C , który jest zdefiniowany w float.h.
-DBL_MAX
aby był dokładnie reprezentowalny, więc jeśli sprzęt FP nie jest w stanie tego zrobić, implementacja musi to obejść. Zobacz model zmiennoprzecinkowy w 5.2.4.2.2 Charakterystyka typów zmiennoprzecinkowych <float.h> p2 z C99 (od tamtej pory mogły zostać przeniesione w inne miejsce).
DBL_MAX
jest dokładnie (1 - b ^ −p) b ^ e_max, co jest dokładnie reprezentowalne, najbardziej ujemna wartość skończona to dokładnie - (1 - b ^ −p) b ^ e_max, a ponieważ tak się składa, że jest dokładnie -DBL_MAX
, negowanie DBL_MAX
również nie może wprowadzać żadnych błędów zaokrągleń.
Liczby zmiennoprzecinkowe (IEEE 754) są symetryczne, więc jeśli możesz przedstawić największą wartość ( DBL_MAX
lub numeric_limits<double>::max()
), po prostu dodaj znak minus na początku.
A potem jest fajny sposób:
double f;
(*((long long*)&f))= ~(1LL<<52);
W C użyj
#include <float.h>
const double lowest_double = -DBL_MAX;
W C ++ pre-11 użyj
#include <limits>
const double lowest_double = -std::numeric_limits<double>::max();
W C ++ 11 i nowszych wersjach użyj
#include <limits>
constexpr double lowest_double = std::numeric_limits<double>::lowest();
min()
funkcja nie była dostępna przed C ++ 11? A może to inna wartość niż -max()
? en.cppreference.com/w/cpp/types/numeric_limits
min
otrzymujesz najmniejszą dodatnią wartość wielkości i lowest
największą ujemną wartość. Tak, to straszne. Witamy w cudownym świecie biblioteki standardowej C ++ :-P
.
float.h
. limits.h
dotyczy liczb całkowitych
Spróbuj tego:
-1 * numeric_limits<double>::max()
Odniesienie: numeric_limits
Ta klasa jest wyspecjalizowana dla każdego z typów podstawowych, a jej elementy członkowskie zwracają lub są ustawione na różne wartości, które definiują właściwości tego typu na określonej platformie, na której jest kompilowany.
-numeric_limits<double>::max()
?
-1 * ...
aby uczynić go nieco jaśniejszym.
Szukasz rzeczywistej nieskończoności lub minimalnej wartości skończonej? Jeśli pierwszy, użyj
-numeric_limits<double>::infinity()
który działa tylko wtedy, gdy
numeric_limits<double>::has_infinity
W przeciwnym razie powinieneś użyć
numeric_limits<double>::lowest()
który został wprowadzony w C ++ 11.
Jeśli lowest()
nie jest dostępny, możesz wrócić do
-numeric_limits<double>::max()
które mogą się różnić od lowest()
zasady, ale zwykle nie jest w praktyce.
-numeric_limits<double>::max()
nawet jeśli to działa w praktyce, nie jest w pełni przenośne w teorii.
Począwszy od C ++ 11 możesz użyć numeric_limits<double>::lowest()
. Zgodnie ze standardem zwraca dokładnie to, czego szukasz:
Skończona wartość x taka, że nie ma innej skończonej wartości y, gdzie
y < x
.
Ma znaczenie dla wszystkich specjalizacji, w którychis_bounded != false
.
Istnieje wiele odpowiedzi -std::numeric_limits<double>::max()
.
Na szczęście sprawdzą się w większości przypadków. Schematy kodowania zmiennoprzecinkowego rozkładają liczbę w mantysie i wykładniku, a większość z nich (np. Popularny IEEE-754 ) używa odrębnego bitu znaku, który nie należy do mantysy. Pozwala to przekształcić największy dodatni w najmniejszy ujemny, po prostu odwracając znak:
Standard nie narzuca żadnego standardu zmiennoprzecinkowego.
Zgadzam się, że mój argument jest trochę teoretyczny, ale przypuśćmy, że jakiś ekscentryczny twórca kompilatorów użyłby rewolucyjnego schematu kodowania z mantysą zakodowaną w pewnych odmianach dopełnienia do dwóch . Kodowanie dopełniające do dwóch nie jest symetryczne. na przykład dla znaku 8-bitowego ze znakiem maksymalna wartość dodatnia wynosi 127, ale minimalna wartość ujemna to -128. Więc możemy sobie wyobrazić, że niektóre kodowania zmiennoprzecinkowe wykazują podobne asymetryczne zachowanie.
Nie znam żadnego takiego schematu kodowania, ale chodzi o to, że standard nie gwarantuje, że odwracanie znaku daje zamierzony wynik . Więc tej popularnej odpowiedzi (przepraszam!) Nie można uznać za w pełni przenośne standardowe rozwiązanie! / * przynajmniej nie, jeśli nie zapewniłeś, że numeric_limits<double>::is_iec559
to prawda * /
Pierwotne pytanie dotyczy nieskończoności. Dlaczego więc nie użyć
#define Infinity ((double)(42 / 0.0))
zgodnie z definicją IEEE? Możesz to oczywiście zaprzeczyć.
numeric_limits<double>::has_infinity && ! numeric_limits<double>::traps
Czy istnieje standardowy i / lub przenośny sposób reprezentowania najmniejszej wartości ujemnej (np. Użycie ujemnej nieskończoności) w programie C (++)?
Podejście C.
Wiele implementacji obsługuje nieskończoność +/-, więc najbardziej ujemna double
wartość to -INFINITY
.
#include <math.h>
double most_negative = -INFINITY;
Czy istnieje sposób standardowy i / lub przenośny ....?
Teraz musimy wziąć pod uwagę również inne przypadki:
Po prostu -DBL_MAX
.
Spodziewałbym się w tym przypadku, wolałby OP -DBL_MAX
.
DBL_MAX
.Jest to niezwykły przypadek, prawdopodobnie poza obawami OP. Gdy double
jest zakodowany jako para liczb zmiennoprzecinkowych, aby osiągnąć pożądany zakres / precesję (patrz double-double ), istnieje maksymalna normalna double
i być może większa niż normalna . Widziałem debatę, czy DBL_MAX
należy odnosić się do największej normy , największej z obu.
Na szczęście to sparowane podejście zwykle obejmuje -nieskończoność, więc pozostaje najbardziej ujemna wartość -INFINITY
.
Aby zapewnić większą przenośność, kod może iść w dół trasy
// HUGE_VAL is designed to be infinity or DBL_MAX (when infinites are not implemented)
// .. yet is problematic with unsigned infinity.
double most_negative1 = -HUGE_VAL;
// Fairly portable, unless system does not understand "INF"
double most_negative2 = strtod("-INF", (char **) NULL);
// Pragmatic
double most_negative3 = strtod("-1.0e999999999", (char **) NULL);
// Somewhat time-consuming
double most_negative4 = pow(-DBL_MAX, 0xFFFF /* odd value */);
// My suggestion
double most_negative5 = (-DBL_MAX)*DBL_MAX;
Jeśli nie masz włączonych wyjątków typu float (których nie powinieneś imho), możesz po prostu powiedzieć:
double neg_inf = -1/0.0;
Daje to ujemną nieskończoność. Jeśli potrzebujesz pływaka, możesz rzucić wynik
float neg_inf = (float)-1/0.0;
lub użyj arytmetyki pojedynczej precyzji
float neg_inf = -1.0f/0.0f;
Wynik jest zawsze taki sam, istnieje dokładnie jedna reprezentacja ujemnej nieskończoności zarówno w pojedynczej, jak i podwójnej precyzji, i są one konwertowane na siebie zgodnie z oczekiwaniami.
-INFINITY
neg_inf
inicjalizacja ma stałą wartość . Kompilator zajmie się obliczeniem inf
wartości. A kiedy użyjesz go jako wartości null do obliczenia maksimum, pierwsza iteracja na ogół nadpisze ją większą wartością. To znaczy wydajność nie jest problemem. Program operacyjny zawiera konkretnie pytanie o „np. Użycie ujemnej nieskończoności” i -inf
jest rzeczywiście jedyną poprawną odpowiedzią na to pytanie. Głosowałeś w dół za poprawną i przydatną odpowiedź.