2013-02-26 16 views
11

Attualmente sto lavorando sull'espressione range in C++. Quindi quello che voglio è se ho qualche espressione comeCome stampare un doppio valore che è appena inferiore ad un altro doppio valore?

x<1 

Poi il mio

double getMax(...); 

dovrebbe restituire un valore doppio che è appena prima 1.000 (doppia precisione) su una linea numero.

Ho provato a fare questo

double getMax(double& a) 
{ 
    return (a-numeric_limits<double>::min()); 
} 

Ma ancora sto ottenendo stesso valore di una dichiarazione in ritorno.

Penso che il C++ stia convertendolo al doppio più vicino nella dichiarazione cout.

int main() 
{ 
    double a = 32; 
    cout<<scientific<<getMax(a)<<endl; 
    return 0; 
} 

uscita:

3.200000e+001 
+0

Tutto ciò che viene detto, 'getMax' non ha senso per gli intervalli aperti e [' getSup'] (http://en.wikipedia.org/wiki/Supremum) dovrebbe restituire esattamente 1. –

risposta

10

Prima di tutto, è necessario assicurarsi di stampare effettivamente un numero sufficiente di cifre per garantire che vengano visualizzati tutti i valori rappresentabili di double. È possibile farlo nel modo seguente (assicuratevi di #include <iomanip> per questo):

std::cout << std::scientific << std::setprecision(std::numeric_limits<double>::max_digits10) << getMax(a) << std::endl; 

In secondo luogo, numeric_limits<>::min non è appropriato per questo. Se il valore iniziale è 1.0, è possibile utilizzare numeric_limits<double>::epsilon, che è la più piccola differenza da 1.0 che è rappresentabile.

Tuttavia, nell'esempio di codice, il valore iniziale è 32. Epsilon non funziona necessariamente per questo. Calcolare l'epsilon corretto in questo caso è difficile.

Tuttavia, se è possibile utilizzare C++ 11 (*), c'è una funzione nell'intestazione cmath che fa quello che è necessario std::nextafter:

#include <iostream> 
#include <limits> 
#include <iomanip> 
#include <cmath> 

double getMax(double a) 
{ 
    return std::nextafter(a,std::numeric_limits<double>::lowest()); 
} 

int main() 
{ 
    double a = 32; 
    std::cout << std::scientific 
       << std::setprecision(std::numeric_limits<double>::max_digits10) 
       << getMax(a) 
       << std::endl; 
    return 0; 
} 

ho messo sul liveworkspace .

Per spiegare:

double nextafter(double from, double to); 

restituisce il valore successivo rappresentabili del dal in direzione di a. Quindi ho specificato std::numeric_limits<double>::lowest() nella mia chiamata per assicurarmi di ottenere il successivo valore rappresentabile inferiore all'argomento.

(*) Vedere il commento di Tony D qui sotto. Potresti avere accesso a nextafter() senza C++ 11.

+1

La riga commentata non dovrebbe essere semplicemente 'a - a * ... :: epsilon()'? –

+0

Oh, bene, girerà verso zero. E '2 * a * ... :: epsilon()' sarà corretto se arrotondato, ma due volte più grande quando no. Ai ai. –

+0

@JanHudec Il '10' era un residuo di un test eseguito prima dell'invio del codice. L'ho rimosso. Se moltiplicare con 'a' è corretto, non lo so. La scelta del fattore corretto è al di là delle mie conoscenze: il mio punto principale era usare 'nextafter' in C++ 11. Per il calcolo corretto di epsilon, qualcun altro può creare una risposta. – jogojapan

0

Penso che hai l'idea giusta. Controlla Setting the precision of a double without using stream (ios_base::precision) non tanto per la domanda, ma per gli esempi che danno dell'uso di precision. Si potrebbe desiderare di provare qualcosa di simile la stampa con una precisione di 53.

Il mio modo di solito vedere "vicino ma non abbastanza" comporta l'impostazione di una soglia differenza (in genere chiamato epsilon). In tal caso, non si utilizzerà una funzione getMax, ma un epsilon utilizzato nell'utilizzo inferiore a. (.. Si potrebbe fare una classe con il valore epsilon e l'overloading degli operatori Tendo ad evitare l'overloading degli operatori come la peste)

In sostanza, si avrebbe bisogno:

bool lessThanEpsilon(double number, double lessThan, double epsilon) 
{ 
    return (lessThan - number >= epsilon); 
} 

Ci sono altre varietà, naturalmente . Equals controllerebbe if Math.abs(number - equals) < epsilon

Problemi correlati