Differenza tra decimale, float e double in .NET?


Risposte:


2267

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.


58
float/ di doublesolito non rappresentano numeri come 101.101110, normalmente è rappresentato come qualcosa del tipo 1101010 * 2^(01010010)- un esponente
Mingwei Samuel

79
@Hazzard: ecco cosa significa la parte "e la posizione del punto binario" della risposta.
Jon Skeet,

112
Sono sorpreso che non sia già stato detto, floatè una parola chiave alias C # e non è un tipo .Net. è System.Single.. singlee doublesono tipi di punti binari mobili.
Brett Caswell,

54
@BKSpurgeon: Beh, solo nello stesso modo in cui puoi dire che tutto è un tipo binario, a quel punto diventa una definizione abbastanza inutile. Decimale è un tipo decimale in quanto è un numero rappresentato come un significato intero e una scala, in modo che il risultato sia significativo * 10 ^ scala, mentre float e double sono significativi e * 2 ^ scala. Prendi un numero scritto in decimale e sposti il ​​punto decimale abbastanza a destra da avere un numero intero per capire il significato e la scala. Per float / double inizieresti con un numero scritto in binario.
Jon Skeet,

21
Un'altra differenza: float a 32 bit; doppio 64 bit; e decimale 128 bit.
David,

1073

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

65
@Throcrocodilehunter: scusa, ma no. Il decimale può rappresentare tutti i numeri che possono essere rappresentati in notazione decimale, ma non 1/3 per esempio. 1,0 m / 3,0 m valuteranno 0,33333333 ... con un numero grande ma finito di 3 secondi alla fine. Moltiplicarlo per 3 non restituirà un 1,0 esatto.
Erik P.

50
@Throcrocodilehunter: penso che tu stia confondendo accuratezza e precisione. Sono cose diverse in questo contesto. La precisione è il numero di cifre disponibili per rappresentare un numero. Più precisione, meno è necessario arrotondare. Nessun tipo di dati ha una precisione infinita.
Igby Largeman,

13
@Throcrocodilehunter: stai assumendo che il valore che si sta misurando sia esattamente 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 .
Daniel Pryden,

27
@Throcrocodilehunter: hai perso il mio punto. non0.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.
Daniel Pryden,

16
@Throcrocodilehunter: ancora non capisci. Non so come dirlo più chiaramente: in C, se lo fai, 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, 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
Daniel Pryden,

84

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:

  • Una certa perdita di precisione è accettabile in molti calcoli scientifici a causa dei limiti pratici del problema fisico o artefatto da misurare. La perdita di precisione non è accettabile in finanza.
  • Il decimale è molto (molto) più lento del float e del doppio per la maggior parte delle operazioni, principalmente perché le operazioni in virgola mobile vengono eseguite in binario, mentre le operazioni decimali vengono eseguite in base 10 (ovvero float e double sono gestiti dall'hardware FPU, come MMX / SSE , mentre i decimali sono calcolati nel software).
  • Il decimale ha un intervallo di valori inaccettabilmente inferiore rispetto al doppio, nonostante supporti più cifre di precisione. Pertanto, Decimal non può essere utilizzato per rappresentare molti valori scientifici.

5
Se stai effettuando calcoli finanziari, devi assolutamente inserire i tuoi tipi di dati o trovare una buona libreria che soddisfi le tue esatte esigenze. La precisione in un contesto finanziario è definita da organismi (umani) standard e hanno regole localizzate (sia nel tempo che nella geografia) molto specifiche su come eseguire i calcoli. Cose come l'arrotondamento corretto non vengono catturati nei tipi di dati numerici semplici in .Net. La capacità di fare calcoli è solo una piccola parte del puzzle.
James Moore,

76
+---------+----------------+---------+----------+---------------------------------------------+
| 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                               |
+---------+----------------+---------+----------+---------------------------------------------+

Vedi qui per maggiori informazioni .


5
Hai lasciato fuori la differenza più grande, che è la base utilizzata per il tipo decimale (il decimale è memorizzato come base 10, tutti gli altri tipi numerici elencati sono base 2).
BrainSlugs83

1
Gli intervalli di valori per Single e Double non sono rappresentati correttamente nell'immagine sopra o nel post del forum di origine. Dato che non possiamo facilmente sovrascrivere il testo qui, usa il carattere di inserimento: Single dovrebbe essere 10 ^ -45 e 10 ^ 38 e Double dovrebbe essere 10 ^ -324 e 10 ^ 308. Inoltre, MSDN ha il float con un intervallo da -3,4x10 ^ 38 a + 3,4x10 ^ 38. Cerca MSDN per System.Single e System.Double in caso di modifiche al collegamento. Singolo: msdn.microsoft.com/en-us/library/b1e65aza.aspx Doppia: msdn.microsoft.com/en-us/library/678hzkk9.aspx
DeeGee

2
Il decimale è 128 bit ... significa che occupa 16 byte non 12
user1477332

51

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).


1
Mi piace molto questa risposta, in particolare la domanda "contiamo o misuriamo il denaro?" Tuttavia, a parte il denaro, non riesco a pensare a nulla di "contato" che non sia semplicemente intero. Ho visto alcune applicazioni che usano i decimali semplicemente perché il doppio ha troppe cifre significative. In altre parole, il decimale potrebbe essere usato perché C # non ha un tipo quadruplo en.wikipedia.org/wiki/Quadruple-precision_floating-point_format
John Henckel

48

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


1
@RogerLipscombe: considererei 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!).
supercat,

1
La tua risposta implica che la precisione è l'unica differenza tra questi tipi di dati. Dato che l'aritmetica binaria in virgola mobile è generalmente implementata nella FPU hardware , le prestazioni sono una differenza significativa. Questo può essere insignificante per alcune applicazioni, ma è fondamentale per altre.
salpa il

6
@supercat double non è mai corretto nelle applicazioni di contabilità. Perché Double può solo approssimare i valori decimali (anche all'interno della gamma della propria precisione). Questo perché il doppio memorizza i valori in un formato base-2 (binario) -centrico.
BrainSlugs83

2
@ BrainSlugs83: l'uso di tipi a virgola mobile per contenere quantità non di numeri interi sarebbe improprio, ma era storicamente molto comune per le lingue avere tipi di virgola mobile che potevano rappresentare con precisione valori di numeri interi più grandi di quelli che i loro tipi interi potevano rappresentare . Forse l'esempio più estremo fu Turbo-87 i cui soli tipi interi erano limitati da -32768 a +32767, ma il cui 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 ...
supercat

1
... per provare a eseguire la matematica multi-precisione usando un sacco di valori a 16 bit. Per la maggior parte delle altre lingue la differenza non era così estrema, ma per molto tempo è stato molto comune per le lingue non avere alcun tipo intero che andasse oltre 4E9 ma che avesse un 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. ..
supercat

36

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;

1
float.MaxValue+1 == float.MaxValue, proprio come decimal.MaxValue+0.1D == decimal.MaxValue. Forse intendevi qualcosa del genere float.MaxValue*2?
supercat

@supercar Ma non è vero che decimal.MaxValue + 1 == decimal.MaxValue
GorkemHalulu

@supercar decimal.MaxValue + 0.1m == decimal.MaxValue ok
GorkemHalulu

1
Il 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.
supercat

28
  1. Double e float possono essere divisi per zero intero senza eccezioni sia in fase di compilazione che di runtime.
  2. Il decimale non può essere diviso per zero intero. La compilazione fallirà sempre se lo fai.

6
Certamente possono! Hanno anche un paio di valori "magici" come Infinito, Infinito negativo e NaN (non un numero) che lo rendono molto utile per rilevare linee verticali durante il calcolo delle pendenze ... Inoltre, se è necessario decidere tra chiamare float . TryParse, double.TryParse e decimal. TryParse (per rilevare se una stringa è un numero, ad esempio), ti consiglio di usare double o float, poiché analizzeranno correttamente "Infinity", "-Infinity" e "NaN" , mentre i decimali no.
BrainSlugs83,

La compilazione fallisce solo se si tenta di dividere un letterale 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.
Drew Noakes,

@ BrainSlugs83 Tuttavia, potresti non voler analizzare "Infinity" o "NaN" a seconda del contesto. Sembra un buon exploit per l'input dell'utente se lo sviluppatore non è abbastanza rigoroso.
Inverno

28

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!


2
Il "punto qualcosa" che hai citato è generalmente indicato come "la parte frazionaria" di un numero. "Punto mobile" non significa "un numero con un punto qualcosa alla fine"; ma invece "Floating Point" distingue il tipo di numero, al contrario di un numero "Fixed Point" (che può anche memorizzare un valore frazionario); la differenza è se la precisione è fissa o mobile. - I numeri in virgola mobile offrono un intervallo di valori dinamico molto più grande (Min e Max), a costo di precisione, mentre un numero in virgola fissa offre una costante quantità di precisione a costo di intervallo.
BrainSlugs83,

16
  • galleggiante: da ± 1,5 x 10 ^ da -45 a ± 3,4 x 10 ^ 38 (~ 7 cifre significative
  • doppio: ± 5,0 x 10 ^ da -324 a ± 1,7 x 10 ^ 308 (15-16 cifre significative)
  • decimale: ± 1,0 x 10 ^ da -28 a ± 7,9 x 10 ^ 28 (28-29 cifre significative)

9
La differenza è più della semplice precisione. - 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 -∞.
BrainSlugs83,

13

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.


3
Per curiosità, qual era il valore grezzo di cellValue.ToString ()? Decimal. TryParse ("0.00006317592", out val) sembra funzionare ...
micahtan,

11
-1 Non fraintendetemi, se è vero, è molto interessante ma questa è una domanda separata, non è certamente una risposta a questa domanda.
Weston,

2
Forse perché la cella di Excel restituiva un doppio e il valore ToString () era "6.31759E-05", quindi il decimal.Parse () non piaceva la notazione. Scommetto che se avessi controllato il valore di ritorno di Decimal.TryParse () sarebbe stato falso.
SergioL,

2
Le risposte di @weston spesso completano le altre risposte compilando le sfumature che hanno perso. Questa risposta evidenzia una differenza in termini di analisi. È davvero una risposta alla domanda!
Robino,

1
Ehm ... decimal.Parse("0.00006317592")funziona - hai qualcosa da fare. - Forse notazione scientifica?
BrainSlugs83

9

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!


Praticamente tutti i sistemi moderni, anche i telefoni cellulari, hanno il supporto hardware per il doppio; e se il tuo gioco ha anche una fisica semplice, noterai una grande differenza tra double e float. (Ad esempio, il calcolo della velocità / attrito in un semplice asteroidi clone, doppie permettono l'accelerazione di fluire molto più fluida di galleggiante -. Sembra che non dovrebbe importa, ma non totalmente.)
BrainSlugs83

I doppi hanno anche il doppio delle dimensioni dei float, il che significa che è necessario masticare il doppio dei dati, il che compromette le prestazioni della cache. Come sempre, misurare e procedere di conseguenza.
yoyo

7

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


5

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) 

4

In parole semplici:

  1. I tipi di variabili Decimal, Double e Float sono diversi nel modo in cui memorizzano i valori.
  2. La precisione è la differenza principale (si noti che questa non è la singola 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 è a 128 bit tipo di dati in virgola mobile.
  3. La tabella riassuntiva:

/==========================================================================================
    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 .


Cosa aggiunge questa risposta che non è già coperta nelle risposte esistenti? A proposito, il tuo "o" nella riga "decimale" non è corretto: la barra nella pagina Web da cui stai copiando indica la divisione piuttosto che un'alternativa.
Mark Dickinson,

1
E contesterei fortemente che la precisione sia la differenza principale. La differenza principale è la base: virgola mobile decimale contro virgola mobile binaria. Questa differenza è ciò che rende 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).
Mark Dickinson,

2

La principale differenza tra ciascuno di questi è la precisione.

floatè un 32-bitnumero, doubleè un 64-bitnumero ed decimalè un 128-bitnumero.


0
  • 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.


-1

Per definire Decimal, Float e Double in .Net (c #)

devi menzionare i valori come:

Decimal dec = 12M/6;
Double dbl = 11D/6;
float fl = 15F/6;

e controlla i risultati.

E i byte occupati da ciascuno sono

Float - 4
Double - 8
Decimal - 12
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.