2013-11-28 5 views
5

È possibile specificare setprecision per arrotondare i doppi valori quando si esegue il flusso sull'output standard?Come specificare l'arrotondamento setprecision

ofile << std::setprecision(12) << total_run_time/TIME << "\n"; 

uscita: 0,756247615801

ofile << std::setprecision(6)<< total_run_time/TIME << "\n"; 

uscita: 0,756248

Ma ho bisogno l'uscita come 0.756247

Grazie

012.

risposta

14

C'è anche std::fesetround da <cfenv>, che imposta la direzione di arrotondamento:

#include <iostream> 
#include <iomanip> 
#include <cmath> 
#include <cfenv> 

int main() { 
    double runtime = 0.756247615801; 

    // Set rounding direction and output with some precision: 
    const auto prev_round = std::fegetround(); 
    std::fesetround(FE_DOWNWARD);  
    std::cout << "desired: " << std::setprecision(6) << runtime << "\n"; 

    // Restore previous rounding direction and output for testing: 
    std::fesetround(prev_round); 
    std::cout << "default: " << std::setprecision(6) << runtime << "\n"; 
} 

(notare che questi non sono il tipo di commenti mi raccomando, sono solo a scopo di tutoraggio)

uscita:

desired: 0.756247 
default: 0.756248 

Nota importante, t hw: Non ho trovato alcuna menzione nello standard, che gli overload operator<< per i tipi floating hanno per onorare la direzione di arrotondamento.

+0

L'unica soluzione corretta al 100% finora, presupponendo un'implementazione di qualità in cui le funzioni da convertire in decimale rispettano la modalità di arrotondamento. –

+0

@PascalCuoq: Ho aggiunto la parte chiamata 'Nota importante, però' –

+0

@phreshel' fesetround' restituisce "Zero, se la direzione di arrotondamento richiesta è stata impostata correttamente Altrimenti, un valore diverso da zero": http: // www. cplusplus.com/reference/cfenv/fesetround/#return Penso che volessi usare: ['fegetround'] (http://www.cplusplus.com/reference/cfenv/fegetround/) Mi sono preso la libertà di modificare la tua risposta . Sentiti libero di eseguire il rollback se la mia modifica non ha senso. –

2

Moltiplica il risultato della divisione di un milione, converti in un numero intero e dividi per un milione (come un doppio). Avere l'effetto collaterale che std::setprecision non è necessario per l'output.

+2

+1 ma, ovviamente, non ti influenzerà in questo caso, ma presta sempre attenzione a questo approccio per non sovraccaricare il numero intero. – Bathsheba

+0

Questa operazione si eccoverà solo dopo 35.79 minuti (più precisamente, se il numero intero è 32 bit, si immette un comportamento non definito (in pratica molto probabilmente overflow) per total_run_time> = 2147,5.) –

+1

Evita la conversione in 'int' (e il conseguente overflow possibile) usando 'modf' (che rompe un' double' nelle sue parti integrale e frazionaria). –

2

Un altro approccio è quello di sconfiggere l'arrotondamento sottraendo, nel secondo caso, 0,000005 dal double prima di emetterlo:

total_run_time/TIME - 0.000005 

In molti modi preferisco questo in quanto evita il rischio di integer overflow.

+4

Ma introduce possibili errori di arrotondamento, poiché '0.000005' non è esattamente rappresentabile. –

1
std::cout.write(std::to_string(0.756247615801).c_str(), 8); 

Sembra davvero sporco, ma funziona!

+0

potresti renderlo migliore e usare 'std :: string :: substring (0,9)' –

+0

std :: string :: substr crea un oggetto stringa aggiuntivo che non è necessario, quindi ho appena usato write per generare la parte pertinente . –

+0

Ho solo pensato che avrebbe una migliore auto-documentazione, ma hai ragione. –

Problemi correlati