Réglage de la précision décimale, .net
Question
Ces lignes en 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);
Génère cette sortie:
2
2.0
2.00000000
2.000000000000000000000000000
Je peux voir que la création d'une variable décimale d'un littéral me permet de contrôler la précision.
- Puis-je régler la précision des variables décimales sans utiliser littéraux?
- Comment puis-je créer b d'un? Comment puis-je créer b de c?
La solution
Préserver zéros comme celui-ci a été introduit dans le .NET 1.1 pour la conformité plus stricte avec la spécification ECMA CLI.
Il y a quelques informations sur ce sur MSDN, par exemple .
Vous pouvez régler la précision comme suit:
-
Math.Round (ou au plafond, plancher, etc.) afin de réduire la précision (b de c)
-
Multiplier par 1.000 ... (avec le nombre de décimales que vous voulez) pour augmenter la précision - par exemple multiplier par 1,0 pour obtenir b à partir de a.
Autres conseils
Vous voyez juste différentes représentations des mêmes données. La précision d'un decimal
sera mis à l'échelle pour être aussi grand qu'il doit être (dans la raison).
De System.Decimal
:
Un nombre décimal est une virgule flottante La valeur qui se compose d'un signe, un valeur numérique où chaque chiffre dans la La valeur varie de 0 à 9, et a facteur d'échelle qui indique la position d'une virgule flottante qui sépare l'intégrale et les fractions de la valeur numérique.
La représentation binaire d'une décimale La valeur est constituée d'un panneau 1-bit, un nombre entier de 96 bits, et une mise à l'échelle facteur utilisé pour diviser les 96 bits entier et préciser quelle partie de celui-ci est une fraction décimale. la mise à l'échelle facteur est implicitement le numéro 10, élevé à un exposant compris entre 0 et à 28. Par conséquent, le binaire représentation d'une valeur décimale est de la forme ((-2 96 2 96 ) / 10 (0 à 28) ), où -2 96 -1 est égal à MinValue, et 2 96 -1 est égal à MaxValue.
Le facteur d'échelle conserve également toute zéros à la fin dans un nombre décimal. n'affectent zéros pas la La valeur d'un nombre décimal en des opérations arithmétiques ou de comparaison. Cependant, de fuite peuvent être des zéros révélée par la méthode ToString si un chaîne de format appropriée est appliquée.
Qu'en est- Math.Round (décimal d, int décimales) ?
J'ai trouvé que je pouvais « toucher » à l'échelle en multipliant ou en divisant par une fantaisie 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;
Je peux fabriquer une suffisamment précise 1 pour modifier les facteurs d'échelle par tailles connues.
decimal scaleFactorBase = 1.0m;
decimal scaleFactor = 1m;
int scaleFactorSize = 3;
for (int i = 0; i < scaleFactorSize; i++)
{
scaleFactor *= scaleFactorBase;
}
decimal z = a * scaleFactor;
Il est tentant de confondre decimal
dans SQL Server avec decimal
dans .NET; ils sont tout à fait différents.
A decimal
SQL Server sont fixés lors de la définition de la colonne ou variable un nombre à virgule fixe dont la précision et l'échelle.
A decimal
NET est un nombre à virgule flottante comme float
et double
(la différence étant que decimal
conserve avec précision alors que les chiffres décimaux float
et double
conserver avec précision des chiffres binaires). Toute tentative de contrôler la précision d'un decimal
.NET est inutile, puisque tous les calculs donneront les mêmes résultats quelle que soit la présence ou l'absence de zéros de remplissage.
La question est - avez-vous vraiment besoin de la précision stored dans la décimale, plutôt que de simplement afficher la décimale à la précision requise. La plupart des applications savent comment interne précise qu'ils veulent être et afficher à ce niveau de précision. Par exemple, même si un utilisateur entre une facture pour 100 dans un paquet de comptes, il imprime toujours comme 100,00 utilisant quelque chose comme val.ToString ( « n2 »).
Comment puis-je créer b d'un? Comment puis-je créer b de c?
c à b est possible.
Console.WriteLine(Math.Round(2.00000000m, 1))
produit 2,0
a à b est délicate car le concept de l'introduction de précision est un peu étranger aux mathématiques.
Je suppose un horrible hack pourrait être un aller-retour.
decimal b = Decimal.Parse(a.ToString("#.0"));
Console.WriteLine(b);
produit 2,0
Cela supprime tous les zéros de la décimale et vous pouvez simplement utiliser ToString()
.
public static class DecimalExtensions
{
public static Decimal Normalize(this Decimal value)
{
return value / 1.000000000000000000000000000000000m;
}
}
Ou bien, si vous voulez un nombre exact de zéros, disons 5, normalisent d'abord (), puis multiplier par 1.00000m.