Regolazione precisione decimale, .net
Domanda
Queste righe in C #
decimal a = 2m;
decimal b = 2.0m;
decimal c = 2.00000000m;
decimal d = 2.000000000000000000000000000m;
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
Genera questa uscita:
2
2.0
2.00000000
2.000000000000000000000000000
Così posso vedere che la creazione di una variabile decimale da un letterale mi permette di controllare la precisione.
- Posso regolare la precisione delle variabili decimali senza usare letterali?
- Come si può creare b da un? Come posso creare b da c?
Soluzione
Preservare zeri finali come questo è stato introdotto nel .NET 1.1 per più stretta conformità con la specifica ECMA CLI.
C'è un po 'di informazioni su MSDN, ad esempio, qui .
È possibile regolare la precisione nel seguente modo:
-
Math.round (oa soffitto, pavimento ecc) per diminuire la precisione (b da c)
-
Moltiplicare per 1.000 ... (con il numero di decimali che si desidera) per aumentare la precisione - per esempio moltiplicare per 1,0 M per ottenere b da un.
Altri suggerimenti
Si sono appena vedendo diverse rappresentazioni degli stessi dati esatti. La precisione di un decimal
verrà dimensionata per essere grande come deve essere (entro limiti ragionevoli).
Un numero decimale è una virgola mobile valore che è costituito da un segno, un valore numerico dove ogni cifra del valore varia da 0 a 9, e un fattore di scala che indica la posizione di un punto decimale fluttuante che separa l'integrale e parti frazionarie del valore numerico.
La rappresentazione binaria di un numero decimale il valore è costituito da un segno a 1 bit, un numero intero 96 bit, e una scalatura fattore utilizzato per dividere il 96 bit intero e specificare quale porzione di essa è una frazione decimale. la scala fattore è implicitamente il numero 10, elevata a un esponente compreso tra 0 a 28. Pertanto, il binario rappresentazione di un valore decimale è della forma, ((-2 96 2 96 ) / 10 (da 0 a 28) ), dove -2 96 -1 è uguale a MinValue e 2 96 -1 è uguale a MaxValue.
Il fattore di scala conserva anche qualsiasi zeri finali in un numero decimale. zeri finali non influiscono sulla valore di un numero decimale operazioni aritmetiche o di confronto. Tuttavia, zeri finali possono essere rivelata dal metodo ToString se un viene applicato appropriata stringa di formato.
Che dire Math.round (decimale d, int decimali) ?
ho scoperto che potevo "tamper" con la scala moltiplicando o dividendo per una fantasia 1.
decimal a = 2m;
decimal c = 2.00000000m;
decimal PreciseOne = 1.000000000000000000000000000000m;
//add maximum trailing zeros to a
decimal x = a * PreciseOne;
//remove all trailing zeros from c
decimal y = c / PreciseOne;
posso fabbricare sufficientemente precisa 1 per modificare i fattori di scala dai formati noti.
decimal scaleFactorBase = 1.0m;
decimal scaleFactor = 1m;
int scaleFactorSize = 3;
for (int i = 0; i < scaleFactorSize; i++)
{
scaleFactor *= scaleFactorBase;
}
decimal z = a * scaleFactor;
E 'forte la tentazione di confondere i decimal
in SQL Server con decimal
in .NET; essi sono molto diversi.
A decimal
SQL Server è un numero a virgola fissa la cui precisione e scala sono fissi quando la colonna o variabile è definita.
A decimal
NET è un numero a virgola mobile come float
e double
(la differenza che decimal
conserva accuratamente cifre decimali che float
e double
preservare accuratamente cifre binarie). Tentare di controllare la precisione di un decimal
NET è inutile, dal momento che tutti i calcoli produrranno gli stessi risultati indipendentemente dalla presenza o assenza di zeri imbottitura.
La domanda è - non si ha realmente bisogno la precisione memorizzato nel decimale, piuttosto che visualizzare il decimale alla precisione richiesta. La maggior parte delle applicazioni sanno internamente come precisa vogliono essere e visualizzare a quel livello di precisione. Ad esempio, anche se un utente inserisce una fattura per 100 in un pacchetto di conti, esso stampa ancora fuori da 100.00 usando qualcosa come val.ToString ( "n2").
Come posso creare b da un? Come posso creare b da c?
c a B è possibile.
Console.WriteLine(Math.Round(2.00000000m, 1))
produce 2.0
A a B è difficile in quanto il concetto di introdurre la precisione è un piccolo alieno alla matematica.
Credo che un orribile hack potrebbe essere un viaggio di andata.
decimal b = Decimal.Parse(a.ToString("#.0"));
Console.WriteLine(b);
produce 2.0
Questo eliminerà tutti i zeri finali del decimale e quindi si può semplicemente utilizzare ToString()
.
public static class DecimalExtensions
{
public static Decimal Normalize(this Decimal value)
{
return value / 1.000000000000000000000000000000000m;
}
}
In alternativa, se si desidera che un numero esatto di zeri finali, diciamo 5, prima Normalizzare () e poi moltiplicare per 1.00000m.