Esiste un modo standard e / o portabile per rappresentare il valore negativo più piccolo (ad esempio per usare l'infinito negativo) in un programma C (++)?
DBL_MIN in float.h è il numero positivo più piccolo .
Esiste un modo standard e / o portabile per rappresentare il valore negativo più piccolo (ad esempio per usare l'infinito negativo) in un programma C (++)?
DBL_MIN in float.h è il numero positivo più piccolo .
Risposte:
-DBL_MAX in ANSI C , che è definito in float.h.
-DBL_MAXdi essere esattamente rappresentabile, quindi se l'hardware FP non è in grado di farlo, l'implementazione deve solo aggirarlo . Vedere il modello a virgola mobile in 5.2.4.2.2 Caratteristiche dei tipi mobili <float.h> p2 di C99 (potrebbe essere stato spostato altrove da allora).
DBL_MAXè esattamente (1 - b ^ −p) b ^ e_max, che è esattamente rappresentabile, il valore finito più negativo è esattamente - (1 - b ^ −p) b ^ e_max, e poiché ciò è esattamente -DBL_MAX, la negazione DBL_MAXnon può introdurre alcun errore di arrotondamento.
I numeri in virgola mobile (IEEE 754) sono simmetrici, quindi se puoi rappresentare il valore più grande ( DBL_MAXo numeric_limits<double>::max()), anteponi semplicemente un segno meno.
E poi è il modo interessante:
double f;
(*((long long*)&f))= ~(1LL<<52);
In C, usa
#include <float.h>
const double lowest_double = -DBL_MAX;
In C ++ pre-11, usa
#include <limits>
const double lowest_double = -std::numeric_limits<double>::max();
In C ++ 11 e versioni successive, usa
#include <limits>
constexpr double lowest_double = std::numeric_limits<double>::lowest();
min()funzione non era disponibile prima di C ++ 11? O è un valore diverso da -max()? en.cppreference.com/w/cpp/types/numeric_limits
minottieni il valore positivo più piccolo in magnitudine e lowestil valore negativo più grande in magnitudine. Sì, è terribile. Benvenuto nel fantastico mondo della libreria standard C ++ :-P.
float.h. limits.hè per numeri interi
Prova questo:
-1 * numeric_limits<double>::max()
Riferimento: numeric_limits
Questa classe è specializzata per ciascuno dei tipi fondamentali, con i suoi membri che restituiscono o impostano i diversi valori che definiscono le proprietà di quel tipo nella piattaforma specifica in cui viene compilato.
-numeric_limits<double>::max()?
-1 * ...per renderlo un po 'più chiaro.
Cerchi l'infinito effettivo o il valore finito minimo? Se il primo, usa
-numeric_limits<double>::infinity()
che funziona solo se
numeric_limits<double>::has_infinity
Altrimenti, dovresti usare
numeric_limits<double>::lowest()
che è stato introdotto in C ++ 11.
Se lowest()non è disponibile, puoi ricorrere a
-numeric_limits<double>::max()
che può differire lowest()in linea di principio, ma normalmente non in pratica.
-numeric_limits<double>::max()anche se funziona in pratica, non è completamente portabile in teoria.
A partire da C ++ 11 puoi usare numeric_limits<double>::lowest(). Secondo lo standard, restituisce esattamente quello che stai cercando:
Un valore finito x tale che non ci siano altri valori finiti y dove
y < x.
Significativo per tutte le specializzazioni in cuiis_bounded != false.
Ci sono molte risposte -std::numeric_limits<double>::max().
Fortunatamente, funzioneranno bene nella maggior parte dei casi. Gli schemi di codifica in virgola mobile scompongono un numero in una mantissa e un esponente e la maggior parte di essi (ad esempio il popolare IEEE-754 ) utilizza un bit di segno distinto, che non appartiene alla mantissa. Questo permette di trasformare il più grande positivo nel più piccolo negativo semplicemente capovolgendo il segno:
Lo standard non impone alcuno standard in virgola mobile.
Sono d'accordo che la mia argomentazione sia un po 'teorica, ma supponiamo che qualche compilatore eccentrico utilizzi uno schema di codifica rivoluzionario con una mantissa codificata in alcune varianti di un complemento a due . La codifica in complemento di due non è simmetrica. ad esempio per un carattere a 8 bit con segno il massimo positivo è 127, ma il minimo negativo è -128. Quindi possiamo immaginare che una codifica in virgola mobile mostri un comportamento asimmetrico simile.
Non sono a conoscenza di alcuno schema di codifica del genere, ma il punto è che lo standard non garantisce che il capovolgimento del segno produca il risultato desiderato . Quindi questa risposta popolare (scusate ragazzi!) Non può essere considerata una soluzione standard completamente portatile! / * almeno non se non hai affermato che numeric_limits<double>::is_iec559è vero * /
La domanda originale riguarda l'infinito. Quindi, perché non usare
#define Infinity ((double)(42 / 0.0))
secondo la definizione IEEE? Puoi negarlo ovviamente.
numeric_limits<double>::has_infinity && ! numeric_limits<double>::traps
Esiste un modo standard e / o portabile per rappresentare il valore negativo più piccolo (ad esempio per usare l'infinito negativo) in un programma C (++)?
Approccio C.
Molte implementazioni supportano +/- infiniti, quindi il doublevalore più negativo è -INFINITY.
#include <math.h>
double most_negative = -INFINITY;
Esiste un modo standard e / o portatile ...?
Ora dobbiamo considerare anche altri casi:
Semplicemente -DBL_MAX.
Mi aspetto che in questo caso OP preferirei -DBL_MAX.
DBL_MAX.Questo è un caso insolito, probabilmente al di fuori delle preoccupazioni di OP. Quando doubleè codificato come una coppia di punti mobili per ottenere l'intervallo / precessione desiderato, (vedere doppio-doppio ) esiste un normale massimo doublee forse uno più normale . Ho visto dibattiti se DBL_MAXdovrebbe riferirsi alla più grande normalità , alla più grande di entrambe.
Fortunatamente questo approccio accoppiato di solito include un -infinity, quindi rimane il valore più negativo -INFINITY.
Per una maggiore portabilità, il codice può seguire il percorso
// 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;
Se non hai le eccezioni float abilitate (cosa che non dovresti imho), puoi semplicemente dire:
double neg_inf = -1/0.0;
Questo produce un infinito negativo. Se hai bisogno di un galleggiante, puoi lanciare il risultato
float neg_inf = (float)-1/0.0;
o usa l'aritmetica a precisione singola
float neg_inf = -1.0f/0.0f;
Il risultato è sempre lo stesso, c'è esattamente una rappresentazione dell'infinito negativo in precisione singola e doppia e si convertono tra loro come ci si aspetterebbe.
-INFINITY
neg_infè inizializzato a un valore costante . Il compilatore si occuperà di calcolare il infvalore. E quando lo usi come valore nullo per calcolare un massimo, la prima iterazione lo sovrascriverà generalmente con un valore maggiore. Cioè le prestazioni non sono certo un problema. E l'OP chiede specificamente "ad esempio di usare l'infinito negativo", ed -infè in effetti l'unica risposta corretta a questo. Hai downvotato una risposta corretta e utile.