2013-03-10 12 views
15

PHP ha un tipo decimale, che non ha l'imprecisione di float e double, in modo che 2.5 + 2.5 = 5 e non 4.999999999978325 o qualcosa del genere.Tipo di dati decimale esatto per C++?

Quindi mi chiedo se esiste un'implementazione di questo tipo di dati per C o C++?

+0

Hai guardato questo? http://gcc.gnu.org/onlinedocs/gcc-4.6.0/libstdc++/api/a01152.html – kfmfe04

+4

Cosa stai chiedendo? 2.5 + 2.5 è 5.0 anche in C !? –

+0

duplicati con questo: http://stackoverflow.com/questions/14096026/c-decimal-data-types – zzk

risposta

6

Sì:

Esistono librerie di precisione arbitrarie per C++.
Un buon esempio è The GNU Multiple Precision arithmetic library.

+2

Nota che questo non risolverà in realtà il problema generale: lo rimanderà a un livello di precisione più profondo che puoi scegliere. Meglio di niente, ma - purtroppo - solo un passo oltre, verso l'impossibile "precisione infinita". Bel consiglio, comunque! –

+0

@EmilioGaravaglia: No. Precisione arbitraria significa esattamente questo. Fa esattamente la matematica. L'unica limitazione è la memoria sulla tua macchina per rappresentare i numeri. –

+3

qual è il punto sta dicendo "No:" e quindi descrivendo lo stesso concetto con una formulazione diversa? Cosa significa "no"? –

-3

Essendo un linguaggio di livello superiore PHP interrompe appena ciò che chiami "imprecisione" ma è certamente lì. In C/C++ è possibile ottenere un effetto simile convertendo il risultato in un tipo intero.

+0

Se la precisione è tale, lanciare a un numero intero sarebbe una cosa molto stupida da fare. Può funzionare bene nel caso del risultato 4.999999999978325 ma sarà una pessima chiamata per tutto ciò che non dovrebbe essere arrotondato a un numero intero. – dtech

+0

@ddriver Beh, come pensi che PHP decida di rappresentare il risultato di 2.5 + 2.5 come 5? Se non dovrebbe essere arrotondato, non arrotondarlo, mi dispiace per la tautologia. – SomeWittyUsername

3

quello che stai chiedendo è anti-fisica.

Nei phyton (e C++ pure) do viene interrotta l'inesattezza arrotondando il risultato al momento di stamparlo, riducendo il numero di cifre significative:

double x = 2.5; 
x += 2.5; 
std::cout << x << std::endl; 

rende solo x essere stampato con 6 cifre decimali di precisione (mentre x stesso ha più di 12), e sarà arrotondato come 5, eliminando l'imprecisione.

alternative non utilizzano virgola mobile a tutti, e implementano tipi di dati che si limitano integer "scalati" aritmetica: 25/10 + 25/10 = 50/10;

noti, tuttavia, che questo ridurrà il limite superiore rappresentato da ciascun tipo intero. Il guadagno in precisione (ed esattezza) si tradurrà in una maggiore velocità di trabocco.

L'aritmetica razionale è anche possibile (ogni numero è rappresentato da un "numarator" e un "denominatore"), senza alcuna perdita di precisione contro le divisioni, (che -Infatti- non sono fatti a meno che esatti) ma ancora, con l'aumentare valori al crescere del numero di operazioni (meno "razionale" è il numero, più grande è il numeratore e il denominatore) con maggiore rischio di overflow.

In altre parole il fatto che un numero finito di bit sia utilizzato (non importa quanto organizzato) provocherà sempre una perdita da pagare sul lato del piccolo sul lato dei grandi numeri.

5

Ci sarà sempre un po 'di precisione. Su qualsiasi computer in qualsiasi rappresentazione numerica ci saranno sempre numeri che possono essere rappresentati con precisione, e altri numeri che non possono.

  • I computer utilizzano un sistema di base 2. Numeri come 0.5 (2^-1), 0.125 (2^-3), 0.325 (2^-2 + 2^-3) saranno rappresentati con precisione (0.1, 0.001, 0.011 per i casi precedenti).

  • In un sistema di base 3 quei numeri non possono essere rappresentati con precisione (metà sarebbe 0,111,111 mila ...), ma altri numeri possono essere accurati (es 2/3 sarebbe 0,2)

  • Anche in base umana 10 sistema ci sono numeri che non possono essere rappresentati con precisione, per esempio 1/3.

  • È possibile utilizzare la rappresentazione del numero razionale e tutto quanto sopra sarà accurato (1/2, 1/3, 3/8 ecc.) Ma ci saranno sempre anche alcuni numeri irrazionali.Sei anche praticamente limitato dalle dimensioni dei numeri interi di questa rappresentazione.

  • Per ogni numero non rappresentabile è possibile estendere la rappresentazione per includerla esplicitamente. (per esempio confrontare i numeri razionali e una rappresentazione a/b + c/d*sqrt(2)), ma ci saranno sempre più numeri che ancora non possono essere rappresentati con precisione. C'è una prova matematica che dice così.

Quindi, lascia che ti chieda questo: di cosa hai esattamente bisogno? Forse calcolo preciso su numeri decimali, ad es. in qualche calcolo monetario?

19

La libreria Boost.Multiprecision ha una classe di modelli in virgola mobile decimale chiamata cpp_dec_float, per la quale è possibile specificare qualsiasi precisione desiderata.

#include <iostream> 
#include <iomanip> 
#include <boost/multiprecision/cpp_dec_float.hpp> 

int main() 
{ 
    namespace mp = boost::multiprecision; 
    // here I'm using a predefined type that stores 100 digits, 
    // but you can create custom types very easily with any level 
    // of precision you want. 
    typedef mp::cpp_dec_float_100 decimal; 

    decimal tiny("0.0000000000000000000000000000000000000000000001"); 
    decimal huge("100000000000000000000000000000000000000000000000"); 
    decimal a = tiny;   

    while (a != huge) 
    { 
     std::cout.precision(100); 
     std::cout << std::fixed << a << '\n'; 
     a *= 10; 
    }  
} 
Problemi correlati