9
votes

Comment puis-je avoir Decimal.TryParse parse 0.0?

Y at-il un moyen d'obtenir Decimal.TryParse pour analyser une valeur de chaîne de « 0.0 » ou « 00.00 » ou « 000.000 » comme 0?

J'ai essayé d'installer NumberStyles Any.


2 commentaires

Pouvez-vous fournir une base à la raison pour laquelle il doit être 0 et non 0,0, 0,00, ou 0.000?


C'est comment nous interprétons un règlement "0 ou n / a" non vide ou 0.0


10 Réponses :


2
votes

Qu'est-ce qui ne fonctionne pas? Cela fonctionne bien pour moi (testé avec "0,0", "00.00" et "000.000"):

decimal d;
if (decimal.TryParse("0.0", NumberStyles.Any, CultureInfo.InvariantCulture, out d))
{
    // use d
}


2 commentaires

La question est que si vous passez dans "0.0" , "0.00" et "0.000" décimal <0.2 ". / Code> à la console, vous verrez 0.0 , 0.00 et 0.000 sur la console respectivement. L'OP demande à voir 0 dans tous les cas.


@Jason: Je n'ai pas interprété la question de la mise en forme d'une décimale comme une chaîne, mais plutôt l'inverse ( "est une façon d'obtenir décimal.tryparse pour analyser une valeur de chaîne" ) , Mais tu as peut-être raison.



6
votes

Y a-t-il un moyen d'obtenir décimal.tryparse pour analyser une valeur de chaîne de "0.0" ou "00.00" ou "000.000" comme 0?

J'interprète votre question à signifier. Dis que je prends les chaînes "0.0" , "00.00" et "000.000" demande décimal.trypsarse pour analyser eux. Lorsque j'écris la décimale résultante à la console, je vois 0.0 , 0.00 et 0.000 respectivement. Existe-t-il un moyen d'obtenir décimal.trypsarse pour renvoyer un décimal dans tous ces cas qui seront écrits sur la console comme 0 ?

non. Pensez à pourquoi cela devrait être. décimal types représentent des nombres précis; Dans certains cercles, 0,00 serait considéré comme plus précis que 0.0 qui serait considéré comme plus précis que 0 . Si décimal.trypsarse tronquait que le type de précision que le type décimal ne serait pas utile à ces fins.

qui dit, il est suffisamment facile de couper le Trailing Zeros avant d'appeler Analys: xxx

utilisation: xxx

sortie: xxx

Veuillez noter que ce qui précède ne montre que le creux de la façon de résoudre votre problème. C'est à vous de décider de décider si vous et comment vous allez gérer les problèmes de localisation. Au minimum, avant de mettre cela en production, vous devez envisager de remplacer le codé dur ". ' avec cultureinfo.currentculture.numberformat.numberdecimalseparator . Vous devriez envisager d'avoir une surcharge de trypsadivertrim avec la même liste de paramètres que décimal.trypsarse . C'est-à-dire: xxx


21 commentaires

@ChRisf: Le point décimal de fuite n'est pas pertinent. décimal.trypsarse corrigera correctement "0. "


Trimtrogerzeros est légèrement trompeur ici car borduer coupera également les zéros.


@Austin Salonen: Tu as raison; Je lui ai donné un meilleur nom. Merci.


Je tire votre point de précision, mais si vous allez jeter des zéros traînants, je pense que vous devriez le faire sur la sortie - et il est trivialement facile à voir avec une chaîne de format.


Mauvaise solution avec un gros bug à l'intérieur! Si vous analysez, par exemple "10" avec votre trimzero, le résultat sera de 1, ce qui est mauvais. Vous devriez soumettre cette réponse à quotidienwtf.com


Qu'en est-il de retour S.Contains (".")? s.trim ('0'): s; pour votre fonction d'assistance?


Correction d'un bug, ajouté un nouveau: votre nouvelle solution fonctionne ... aux États-Unis. Dans les pays européens souvent, un côlon est utilisé au lieu du point pour les fractions. Donc, ce serait "0,00" au lieu de "0,00". Un programme s'appuyant sur votre méthode se brisera à Lotsa Funny Manies.


@Sam: Comment traiter la localisation de ce qui précède est un problème distinct; Si l'OP ne s'attend pas à la commission des Européens ou ne veut pas analyser cette entrée, ce n'est pas un bogue. C'est-à-dire que si la spécification de la méthode est "des décimales analyses formatées comme des chaînes localisées américaines dans des décimales, mais tronquer des zéros traînants après le point décimal", ce que j'ai bien.


"Ce type d'entrée n'arrivera pas" n'est pas une excuse valide pour introduire des bugs dans un système. Surtout, alors quand vous ne savez pas où l'OP veut utiliser la fonction.


"Downvoters: veuillez expliquer" - dans mon cas c'est la question de la localisation indiquée par SAM. Dans l'événement improbable que la spécification charge des chaînes localisées américaines, vous devriez explicitement utiliser cette culture pour analyse. Une solution générale robuste aurait une surcharge qui accepte un iFormatProvider et par défaut à la cultureInfo.Currentculture.


@Sam: Si la spécification de la méthode est "Analysse des décimales formatée comme des chaînes localisées aux États-Unis dans des zéros tronquées décimales mais tronquées après le point décimal", à l'analyse "0,00" comme décimal 0 serait un bug. Le comportement correct serait plutôt de signaler une erreur d'entrée sur cette entrée. Et en ce qui concerne votre commentaire "[e] Spécialement, alors que vous ne savez pas où l'OP veut utiliser la fonction". Touche et retour à vous. C'est pourquoi j'ai dit précédemment que traiter la localisation est un problème distinct de celui-ci.


@Joe: Ne prenez pas sans danger les problèmes. Yagni et tout ça. L'OP peut s'inquiéter de la manière de transformer ce qui précède en code de qualité de production. Aussi, s'il vous plaît voir mon commentaire immédiatement avant celui-ci.


@Jason: Je suis respectueusement en désaccord. Votre code est fragile car il utilise un mélange d'un séparateur décimal câblé («.») Et d'analyse implicitement en utilisant la culture actuelle. Ainsi, en Allemagne, votre code parsa "1,234" sous la forme de 1,234 au lieu de 1234 (période est un séparateur de milliers de personnes). Et attendez-vous à détecter et à corriger ce bogue sans au moins le signaler est un peu beaucoup. Yagni ne signifie pas qu'une solution fragile est acceptable IMHO.


@Joe: Encore une fois, il appartient à l'OP de la meilleure façon de tourner le code de qualité de production. Je suis d'accord avec vous que cela mérite de souligner les problèmes de localisation potentiels; C'est mon expérience que les gens ne sont en général pas assez conscient de ces problèmes. Merci pour les commentaires; Je vais éditer en conséquence.


Regardez, alors que je aussi repéré le bug où votre version originale de TrimZeros tournerait 100 en 1, la question plus fondamentale ici (comme je le vois) est que vous utilisez représentations de chaîne < / i> comme logique back-end aux numéros manipulation. Il y a un problème fondamental là-bas, et vous allez rencontrer des problèmes imprévus au-dessus de ce que les autres ont déjà mentionné. Pourquoi ne pas simplement vérifier si le nombre == analysable 0M, et le cas échéant le retour 0M?


@Dan: Parce que cela serait horriblement fragile. Et si l'OP souhaite également "1,00" à analyser comme 1 ? Je ne vois pas de problème avec faire des manipulations à la chaîne dans un problème d'analyse de cordes.


@ Jason: Je ne suis pas d'accord que ce serait « fragile ». Il ne causerait aucun incorrect comportement ; il serait tout simplement pas faire face aux exigences inexistantes. (Et vous vous avez parlé de YAGNI quelques commentaires en arrière.) Manipulation de chaînes, d'autre part, est très fragile. Par exemple, vous pouvez estimer que vous avez fait affaire avec le 100 -> 1 bug en ajoutant Contient ( « ») chèque, mais qu'en est-la chaîne 0.0? Version (nouveau [] { '0'}) couper des deux côtés, ce qui dans la chaîne . dans ce cas, TryParseAfterTrim échouera et return false.


En d'autres termes, la raison pour laquelle le code semble avoir "travaillé" dans votre exemple est que trypsafertrim a échoué , définissez d d à par défaut ( décimal) (qui est 0M) et renvoyé faux. Si vous ne me croyez pas, essayez de changer le code sur si (trypsafertrim (S, OUT D)) console.writeline (d); vous trouverez rien n'est imprimé.


@Jason: Vous avez maintenant "réparé" le problème que j'ai signalé ci-dessus en convertissant sur Trimend , certes une amélioration. Cependant, à mon avis, votre code est toujours brisé. La chaîne ".000", que décimal.trypsarse analysera correctement comme 0 (0.000) - une valeur numérique facilement convertible en 0 - ne sera pas analysée correctement par votre Trypsafeaftertrim méthode car elle sera d'abord coupée à "". qui n'est pas un nombre. Encore une fois, de mon point de vue, cela démontre la fragilité de votre approche d'utiliser la manipulation de chaîne pour gérer les nombres.


@Dan: soit c'est un bogue dans décimal.trypsarse ou la documentation n'est pas correcte. Selon msdn.microsoft.com/en-us/library/9zbda557.aspx < / a> Le paramètre de chaîne à analyser doit être formaté comme [WS] [signe] [chiffres,] chiffres [. DigitsFraction] [WS] . Notez qu'il existe un fichier non-terminal non optionnel avant le point décimal facultatif. En regardant la documentation, il semble que WhitSpace soit également légal à la fin et que je me suis donc ajusté pour cela aussi.


@ Jason, vous corriger vos bogues de façon hâtive, l'ajout de nouvelles sur le chemin. Et vous essayez maintenant et faites vos insectes disparaissent en appelant les noms. Cela est particulièrement mauvaise depuis SO est conçu comme référentiel de connaissances, et on ne sait jamais qui va lire votre « solution ». Vous ne savez même pas où l'OP veut l'utiliser, vous laissez entendre que des États-Unis.



13
votes

Utilisation du InvariantCulture, decimal.TryParse n'interprète avec succès toutes ces chaînes zéro. Ce code, par exemple:

0
0
0


7 commentaires

Notez que vous avez codé en dur "0.0" dans l'appel à tryparse . Je suis sûr que si vous avez transmis str , vous verriez 0.0 , 0.00 et 0.000 sur la console.


@ Jason - vous avez raison. Je l'ai mis à jour. Le problème n'est pas la conversion en décimal, mais le dos de conversion en une chaîne sur l'impression. Toutes ces valeurs sont toujours à zéro. J'ai mis à jour ma réponse en conséquence.


@tvanfosson: C'est vrai, ils représentent tous nuls, mais ils représentent différents niveaux de précision de zéro.


@Jason - Depuis qu'il veut qu'ils reflètent tous la même précision, je suppose que la précision est moins importante que d'imprimer systématiquement la valeur zéro de la même manière.


J'accepte que vous devriez formater sur l'écran; Ne jetez jamais ce qui a été saisi! Même principe que nous utilisons ici, donc lors de la sauvegarde du corps d'un poste - stockez l'entrée brute, encoder / désinfecter sur l'écran.


Si l'exigence est plus généralement "enlevez les zéros de traînant de toute valeur décimale tout en conservant tous les chiffres significatifs" (pas seulement les trois exemples de l'OP), cette solution ne fonctionne pas, car elle arrondit le résultat maximum d'une décimale maximale. . Au lieu de cela, vous pouvez utiliser une chaîne de format comme G28 ou 0. ############################## comme décrit dans ma réponse.


@ Joe - noté. Vous devez utiliser autant hachage / livres signes que vous avez besoin de chiffres significatifs.



0
votes

Dans votre Console.Writeline, appliquez un format de chaîne pour maintenir la double précision zéro.


0 commentaires

0
votes

Je vois ce que vous voulez dire. Le code suivant:

number = 0.0
number = 0.00
number = 0.000
number = 0.0000


1 commentaires

J'ai fait la même expérience. Je me demande si cela est pour une application scientifique où des chiffres significatifs entrent en jeu ...



1
votes

// Ce sorties 0 données 0.0 comme une chaîne bien ....

 decimal d;

 decimal.TryParse("0.0", out d);

 string s = String.Format("{0:0}", d);


0 commentaires

3
votes

Préservation des zéros de fuite des valeurs décimales a été introduite dans .NET 1.1 pour une conformité plus stricte avec la spécification de la CLI ECMA. Voir Cette réponse à une question similaire .

tandis que la question initiale est limité à l'élimination des zéros traînants lors de l'analyse d'une chaîne, je pense qu'il est important de comprendre pourquoi et dans quelles circonstances traînant des zéros sont préservées dans une représentation interne de la valeur décimale.

Les zéros finaux peuvent apparaître dans une valeur décimale. de:

a) une analyse d'analyse qui a des zéros traînant, comme dans le poteau d'origine, ou

b) à la suite d'un calcul. Par exemple: Multiplier des valeurs décimales 1.2 * 1.5 donne le résultat de 1,80: En effet, en multipliant deux valeurs qui sont précises à un endroit décimal donnent un résultat précis à deux décimales - et le deuxième endroit décimal est donc préservé même si Sa valeur est zéro.

Que faire sur les zéros traînants dans la représentation interne décimale? En général, ne rien faire: vous pouvez formater sur la sortie sur votre nombre de décimales souhaité, ils ne feront donc pas de mal.

Decimal est principalement utilisé pour les calculs financiers, et il est généralement souhaitable de préserver les zéros de fuite afin qu'un Le montant arrondi au cent près est représenté comme 1,20 plutôt que 1,2. Normalement, lors de l'utilisation de décimales, vous travaillerez à une précision fixe (peut-être au cent près d'une demande de vente au détail, ou au centième de cent près de cent lors du calcul des accusations d'utilisation du téléphone mobile). Donc, votre logique d'application s'occupera explicitement de l'arrondi à un nombre fixe de décimales en utilisant des règles d'arrondi explicites, par ex. un calcul de taxe qui tourne dans le cent près, à l'aide de la MidspointRounding.awayfayzero: xxx

si vous ne travaillez pas à un nombre fixe de décimales de cette manière, vous pourriez envisager Que vous deviez utiliser un double plutôt que decimal.

Néanmoins, il peut parfois être nécessaire d'éliminer les zéros traînants tout en conservant tous les chiffres significatifs. Afaik, il n'y a pas de méthode intégrée pour cela.

Si vous avez besoin de le faire, une solution de base serait de formater en tant que chaîne à l'aide de la chaîne de format standard "G28" (équivalente à la chaîne de format personnalisée "0. ######## ##################### "), puis analyser le résultat à une décimale.

une autre manière d'éliminer les zéros traînants sans convertir / d'une chaîne (probablement plus rapide, même si je ne l'ai pas mesuré) est d'utiliser Math.Round - par exemple La méthode suivante: xxx


0 commentaires

1
votes

Un moyen de se débarrasser des zéros traînants après la décimale les éliminerait dans la décimale.

La force de la force brute serait incorporer avec la structure interne de la décimale: xxx

Pas jolie, pas rapide, mais cela changera la représentation interne de "0.000" à "0" dans une décimale.


0 commentaires

1
votes

Pourquoi n'utilisez-vous pas int.tryparse? ou double.tryparse?


0 commentaires

2
votes

Je soumets humblement cette solution: xxx pré>

ne fait-il pas le travail? p>

Voici un exemple complet: P>

string valueString = "0.000";
decimal value;
bool isValid = decimal.TryParse(valueString, out value);
if (isValid)
{
    decimal processedValue = value == 0 ? 0 : value;
    System.Diagnostics.Debug.Print("value: {0}, processedValue: {1}", value, processedValue);
}


0 commentaires