Qual è la differenza tra decimal, floate doublein .NET?
Quando qualcuno userebbe uno di questi?
Qual è la differenza tra decimal, floate doublein .NET?
Quando qualcuno userebbe uno di questi?
Risposte:
floate doublesono tipi di punti binari mobili . In altre parole, rappresentano un numero come questo:
10001.10010110011
Il numero binario e la posizione del punto binario sono entrambi codificati all'interno del valore.
decimalè un tipo di virgola decimale mobile . In altre parole, rappresentano un numero come questo:
12345.65789
Ancora una volta, il numero e la posizione del punto decimale sono entrambi codificati all'interno del valore: questo è ciò che rende decimalancora un tipo a virgola mobile anziché un tipo a virgola fissa.
La cosa importante da notare è che gli umani sono abituati a rappresentare numeri non interi in una forma decimale e si aspettano risultati esatti in rappresentazioni decimali; non tutti i numeri decimali sono esattamente rappresentabili in virgola mobile binaria, ad esempio 0,1, quindi se si utilizza un valore in virgola mobile binaria si ottiene effettivamente un'approssimazione a 0,1. Otterrai comunque approssimazioni anche usando un punto decimale mobile, ad esempio il risultato della divisione 1 per 3 non può essere rappresentato esattamente.
Per quanto riguarda cosa usare quando:
Per valori che sono "decimali esatti per natura" è bene usarli decimal. Questo di solito è adatto a qualsiasi concetto inventato dall'uomo: i valori finanziari sono l'esempio più ovvio, ma ce ne sono anche altri. Considera, ad esempio, il punteggio assegnato ai subacquei o ai pattinatori su ghiaccio.
Per i valori che sono più artefatti della natura che non possono essere misurati esattamente in ogni caso, float/ doublesono più appropriati. Ad esempio, i dati scientifici sarebbero di solito rappresentati in questo modulo. Qui, i valori originali non saranno "decimalmente precisi" per cominciare, quindi non è importante che i risultati previsti mantengano la "precisione decimale". I tipi di punti binari mobili sono molto più veloci con i decimali.
float/ di doublesolito non rappresentano numeri come 101.101110, normalmente è rappresentato come qualcosa del tipo 1101010 * 2^(01010010)- un esponente
floatè una parola chiave alias C # e non è un tipo .Net. è System.Single.. singlee doublesono tipi di punti binari mobili.
La precisione è la differenza principale.
Float - 7 cifre (32 bit)
Doppie -15-16 cifre (64 bit)
Decimali -28-29 cifre significative (128 bit)
I decimali hanno una precisione molto più elevata e vengono generalmente utilizzati all'interno di applicazioni finanziarie che richiedono un elevato grado di accuratezza. I decimali sono molto più lenti (fino a 20 volte volte in alcuni test) rispetto a un doppio / float.
Decimali e float / doppi non possono essere confrontati senza un cast, mentre i float e i doppi possono farlo. I decimali consentono anche la codifica o lo zero finale.
float flt = 1F/3;
double dbl = 1D/3;
decimal dcm = 1M/3;
Console.WriteLine("float: {0} double: {1} decimal: {2}", flt, dbl, dcm);
Risultato:
float: 0.3333333
double: 0.333333333333333
decimal: 0.3333333333333333333333333333
0.1 - questo è raramente il caso nel mondo reale! Qualsiasi formato di archiviazione finito configura un numero infinito di valori possibili in un numero finito di schemi di bit. Ad esempio, floatsi confonderà 0.1e 0.1 + 1e-8, mentre decimalsi confonderà 0.1e 0.1 + 1e-29. Certo, entro un determinato intervallo , alcuni valori possono essere rappresentati in qualsiasi formato con perdita di precisione pari a zero (ad esempio, è floatpossibile memorizzare qualsiasi numero intero fino a 1,6e7 con perdita di precisione pari a zero), ma questa non è ancora precisione infinita .
0.1 è un valore speciale ! L'unica cosa che rende 0.1"migliore" di 0.10000001è perché agli esseri umani piace la base 10. E anche con un floatvalore, se si inizializzano due valori 0.1allo stesso modo, entrambi avranno lo stesso valore . È solo che quel valore non sarà esattamente 0.1 - sarà il valore più vicino a 0.1quello che può essere rappresentato esattamente comefloat . Certo, con float binari (1.0 / 10) * 10 != 1.0, ma anche con float decimali (1.0 / 3) * 3 != 1.0. Nessuno dei due è perfettamente preciso.
double a = 0.1; double b = 0.1;allora a == b sarà vero . È solo questo ae entrambi non bsaranno esattamente uguali . In C #, se lo fai, allora sarà anche vero. Ma in quel caso, né di né sarà esattamente uguale - entrambi saranno uguali . In entrambi i casi, la precisione viene persa a causa della rappresentazione. Dici testardamente che ha una precisione "infinita", che è falsa . 0.1decimal a = 1.0m / 3.0m; decimal b = 1.0m / 3.0m;a == bab1/30.3333...decimal
La struttura decimale è strettamente orientata ai calcoli finanziari che richiedono precisione, che sono relativamente intolleranti all'arrotondamento. I decimali non sono adeguati per le applicazioni scientifiche, tuttavia, per diversi motivi:
+---------+----------------+---------+----------+---------------------------------------------+
| C# | .Net Framework | Signed? | Bytes | Possible Values |
| Type | (System) type | | Occupied | |
+---------+----------------+---------+----------+---------------------------------------------+
| sbyte | System.Sbyte | Yes | 1 | -128 to 127 |
| short | System.Int16 | Yes | 2 | -32768 to 32767 |
| int | System.Int32 | Yes | 4 | -2147483648 to 2147483647 |
| long | System.Int64 | Yes | 8 | -9223372036854775808 to 9223372036854775807 |
| byte | System.Byte | No | 1 | 0 to 255 |
| ushort | System.Uint16 | No | 2 | 0 to 65535 |
| uint | System.UInt32 | No | 4 | 0 to 4294967295 |
| ulong | System.Uint64 | No | 8 | 0 to 18446744073709551615 |
| float | System.Single | Yes | 4 | Approximately ±1.5 x 10-45 to ±3.4 x 1038 |
| | | | | with 7 significant figures |
| double | System.Double | Yes | 8 | Approximately ±5.0 x 10-324 to ±1.7 x 10308 |
| | | | | with 15 or 16 significant figures |
| decimal | System.Decimal | Yes | 12 | Approximately ±1.0 x 10-28 to ±7.9 x 1028 |
| | | | | with 28 or 29 significant figures |
| char | System.Char | N/A | 2 | Any Unicode character (16 bit) |
| bool | System.Boolean | N/A | 1 / 2 | true or false |
+---------+----------------+---------+----------+---------------------------------------------+
Non ribadirò tonnellate di informazioni buone (e alcune cattive) già risposte in altre risposte e commenti, ma risponderò alla tua domanda di follow-up con un suggerimento:
Quando qualcuno userebbe uno di questi?
Usa i decimali per i valori conteggiati
Utilizzare float / double per i valori misurati
Qualche esempio:
denaro (contiamo i soldi o misuriamo i soldi?)
distanza (contiamo la distanza o misuriamo la distanza? *)
punteggi (contiamo i punteggi o misuriamo i punteggi?)
Contiamo sempre il denaro e non dovremmo mai misurarlo. Di solito misuriamo la distanza. Contiamo spesso i punteggi.
* In alcuni casi, ciò che definirei distanza nominale , potremmo davvero voler "contare" la distanza. Ad esempio, forse abbiamo a che fare con segni di paesi che mostrano le distanze dalle città e sappiamo che tali distanze non hanno mai più di una cifra decimale (xxx.x km).
float 7 cifre di precisione
double ha circa 15 cifre di precisione
decimal ha circa 28 cifre di precisione
Se hai bisogno di una maggiore precisione, usa double invece di float. Nelle CPU moderne entrambi i tipi di dati hanno quasi le stesse prestazioni. L'unico vantaggio dell'utilizzo di float è che occupano meno spazio. Praticamente conta solo se ne hai molti.
Ho trovato questo interessante. Ciò che ogni scienziato informatico dovrebbe sapere sull'aritmetica a virgola mobile
doublecorretto nelle applicazioni di contabilità in quei casi (e fondamentalmente solo in quei casi) in cui non era disponibile alcun tipo intero maggiore di 32 bit e doubleveniva utilizzato come se fosse un tipo intero a 53 bit (ad esempio per contenere un numero intero di centesimi o un numero intero di centesimi di centesimo). Oggigiorno non si usano molto per queste cose, ma molte lingue hanno acquisito la capacità di usare valori a virgola mobile a precisione doppia molto prima di guadagnare matematica a 64 bit (o in alcuni casi anche a 32 bit!).
RealIIRC poteva rappresentare valori fino a 1,8E + 19 con precisione unitaria. Penso che sarebbe molto più sicuro che un'applicazione di contabilità utilizzasse Realper rappresentare un numero intero di penny rispetto a ...
doubletipo con una precisione dell'unità fino a 9E15. Se uno ha bisogno di memorizzare numeri interi che sono più grandi del più grande tipo intero disponibile, usare doubleè adatto per essere più semplice ed efficiente rispetto al tentativo di confondere la matematica multi-precisione, specialmente dato che mentre i processori hanno istruzioni per eseguire 16x16-> 32 o. ..
Nessuno lo ha menzionato
Nelle impostazioni predefinite, Floats (System.Single) e doppi (System.Double) non useranno mai il controllo di overflow mentre Decimal (System.Decimal) utilizzerà sempre il controllo di overflow.
intendo
decimal myNumber = decimal.MaxValue;
myNumber += 1;
genera OverflowException .
Ma questi non:
float myNumber = float.MaxValue;
myNumber += 1;
&
double myNumber = double.MaxValue;
myNumber += 1;
float.MaxValue+1 == float.MaxValue, proprio come decimal.MaxValue+0.1D == decimal.MaxValue. Forse intendevi qualcosa del genere float.MaxValue*2?
System.Decimalgenera un'eccezione poco prima che diventi in grado di distinguere le unità intere, ma se si suppone una richiesta a che fare con ad es dollari e centesimi, che potrebbe essere troppo tardi.
decimalper zero (CS0020), e lo stesso vale per i letterali integrali. Tuttavia, se un valore decimale di runtime è diviso per zero, otterrai un'eccezione non un errore di compilazione.
I numeri interi, come detto, sono numeri interi. Non possono memorizzare il punto qualcosa, come .7, .42 e .007. Se è necessario memorizzare numeri che non sono numeri interi, è necessario un diverso tipo di variabile. È possibile utilizzare il tipo doppio o il tipo float. Puoi impostare questi tipi di variabili esattamente nello stesso modo: invece di usare la parola int, digiti doubleo float. Come questo:
float myFloat;
double myDouble;
(float è l'abbreviazione di "virgola mobile" e significa solo un numero con un punto alla fine.)
La differenza tra i due sta nella dimensione dei numeri che possono contenere. Per float, puoi avere fino a 7 cifre nel tuo numero. Per doubles, puoi avere fino a 16 cifre. Per essere più precisi, ecco la dimensione ufficiale:
float: 1.5 × 10^-45 to 3.4 × 10^38
double: 5.0 × 10^-324 to 1.7 × 10^308
float è un numero a 32 bit e double è un numero a 64 bit.
Fare doppio clic sul nuovo pulsante per accedere al codice. Aggiungi le tre righe seguenti al codice del tuo pulsante:
double myDouble;
myDouble = 0.007;
MessageBox.Show(myDouble.ToString());
Arrestare il programma e tornare alla finestra di codifica. Cambia questa riga:
myDouble = 0.007;
myDouble = 12345678.1234567;
Esegui il programma e fai clic sul doppio pulsante. La finestra di messaggio visualizza correttamente il numero. Aggiungi un altro numero alla fine, tuttavia, e C # arrotolerà nuovamente verso l'alto o verso il basso. La morale è se vuoi la precisione, stai attento a arrotondare!
decimalè effettivamente memorizzato in formato decimale (rispetto alla base 2; quindi non perderà o arrotonderà le cifre a causa della conversione tra i due sistemi numerici); inoltre, decimalnon ha alcun concetto di valori speciali come NaN, -0, ∞ o -∞.
Questo è stato un thread interessante per me, dato che oggi abbiamo appena avuto un brutto bug, per quanto riguarda decimalavere meno precisione di un float.
Nel nostro codice C #, stiamo leggendo valori numerici da un foglio di calcolo Excel, li convertiamo in un decimal, quindi li rispediamo decimala un servizio per salvarli in un database di SQL Server .
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
decimal value = 0;
Decimal.TryParse(cellValue.ToString(), out value);
}
Ora, per quasi tutti i nostri valori di Excel, ha funzionato magnificamente. Ma per alcuni valori di Excel molto piccoli, l'utilizzo ha decimal.TryParseperso completamente il valore. Un esempio è
cellValue = 0,00006317592
Decimal.TryParse (cellValue.ToString (), valore out); // restituirebbe 0
La soluzione, stranamente, era convertire i valori di Excel in un doubleprimo e poi in un decimal:
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
double valueDouble = 0;
double.TryParse(cellValue.ToString(), out valueDouble);
decimal value = (decimal) valueDouble;
…
}
Anche se doubleha meno precisione di un decimal, questo in realtà assicura che piccoli numeri saranno comunque riconosciuti. Per qualche motivo, è double.TryParsestato effettivamente in grado di recuperare numeri così piccoli, mentre decimal.TryParseli avrebbe impostati a zero.
Dispari. Molto strano.
decimal.Parse("0.00006317592")funziona - hai qualcosa da fare. - Forse notazione scientifica?
Per applicazioni come giochi e sistemi embedded in cui memoria e prestazioni sono entrambi fondamentali, il float è in genere il tipo di scelta numerica in quanto è più veloce e la metà delle dimensioni di un doppio. I numeri interi erano l'arma preferita, ma le prestazioni in virgola mobile hanno superato i numeri interi nei processori moderni. Decimale è subito!
I tipi di variabili Decimal, Double e Float sono diversi nel modo in cui memorizzano i valori. La precisione è la principale differenza in cui float è un tipo di dati a virgola mobile a precisione singola (32 bit), double è un tipo di dati a virgola mobile a precisione doppia (64 bit) e decimale è un tipo di dati a virgola mobile a 128 bit.
Float - 32 bit (7 cifre)
Doppio - 64 bit (15-16 cifre)
Decimale - 128 bit (28-29 cifre significative)
Maggiori informazioni su ... la differenza tra Decimale, Virgola mobile e Doppio
Il problema con tutti questi tipi è che sussiste una certa imprecisione E che questo problema può verificarsi con piccoli numeri decimali come nell'esempio seguente
Dim fMean as Double = 1.18
Dim fDelta as Double = 0.08
Dim fLimit as Double = 1.1
If fMean - fDelta < fLimit Then
bLower = True
Else
bLower = False
End If
Domanda: quale valore contiene la variabile bLower?
Risposta: su una macchina a 32 bit bLower contiene TRUE !!!
Se sostituisco Double con Decimal, bLower contiene FALSE che è la buona risposta.
In doppio, il problema è che fMean-fDelta = 1.09999999999 che è inferiore a 1.1.
Attenzione: penso che lo stesso problema possa certamente esistere per un altro numero perché Decimale è solo un doppio con maggiore precisione e la precisione ha sempre un limite.
In effetti, Double, Float e Decimal corrispondono al decimale BINARY in COBOL!
È deplorevole che altri tipi numerici implementati in COBOL non esistano in .Net. Per coloro che non conoscono COBOL, in COBOL esiste il seguente tipo numerico
BINARY or COMP like float or double or decimal
PACKED-DECIMAL or COMP-3 (2 digit in 1 byte)
ZONED-DECIMAL (1 digit in 1 byte)
In parole semplici:
/==========================================================================================
Type Bits Have up to Approximate Range
/==========================================================================================
float 32 7 digits -3.4 × 10 ^ (38) to +3.4 × 10 ^ (38)
double 64 15-16 digits ±5.0 × 10 ^ (-324) to ±1.7 × 10 ^ (308)
decimal 128 28-29 significant digits ±7.9 x 10 ^ (28) or (1 to 10 ^ (28)
/==========================================================================================
Puoi leggere di più qui , Float , Double e Decimal .
Decimaladatto per le applicazioni finanziarie ed è il criterio principale da utilizzare quando si decide tra Decimale Double. È raro che la Doubleprecisione non sia sufficiente per applicazioni scientifiche, ad esempio (ed Decimalè spesso inadatta per applicazioni scientifiche a causa della sua portata limitata).
La principale differenza tra ciascuno di questi è la precisione.
floatè un 32-bitnumero, doubleè un 64-bitnumero ed decimalè un 128-bitnumero.
Decimale 128 bit (28-29 cifre significative) In caso di applicazioni finanziarie è meglio usare i tipi decimali perché offre un alto livello di accuratezza e facile da evitare errori di arrotondamento Utilizzare decimale per la matematica non intera dove è necessaria la precisione (ad es. denaro e valuta)
Doppio 64 bit (15-16 cifre) I doppi tipi sono probabilmente il tipo di dati più comunemente usato per valori reali, ad eccezione della gestione del denaro. Usa double per la matematica non intera dove non è necessaria la risposta più precisa.
Float a 32 bit (7 cifre) Viene utilizzato principalmente nelle librerie grafiche perché richieste molto elevate di potenza di elaborazione, utilizza anche situazioni che possono sopportare errori di arrotondamento.
Decimalssono molto più lenti di a double/float.
Decimalse Floats/Doublesnon può essere paragonato senza un cast mentre Floatse Doublespuò.
Decimals consentire anche la codifica o gli zeri finali.
devi menzionare i valori come:
Decimal dec = 12M/6;
Double dbl = 11D/6;
float fl = 15F/6;
e controlla i risultati.
Float - 4
Double - 8
Decimal - 12