105 votes

Analyse des chaînes de caractères pour les doubler avec une virgule et un point

J'essaie d'écrire une fonction qui convertit un tableau de chaînes de caractères en un tableau de chaînes de caractères où tous les doubles du tableau sont arrondis au nombre de décimales que j'ai fixé. Il peut aussi y avoir des chaînes dans le tableau qui ne sont pas du tout des valeurs doubles.

string[,] values = new string[1, 3];

values[0, 0] = "hello";
values[0, 1] = "0.123";
values[0, 2] = "0,123";

int decimalPlaces = 2;

double tmp;
string format = "F" + decimalPlaces.ToString();
IFormatProvider provider = CultureInfo.InvariantCulture;
for (int i = 0; i < values.GetLength(0); i++)
{
    for (int j = 0; j < values.GetLength(1); j++)
    {
        if (double.TryParse(values[i, j], out tmp))
        {
            values[i, j] = tmp.ToString(format, provider);
        }
    }
}

Console.ReadLine();

Le résultat doit être : "hello" , "0.12", "0.12" mais "hello", "123.00", "0.12" traitera la virgule de la mauvaise manière. Quelqu'un a-t-il une solution simple et efficace ?

202voto

phq Points 1851

Pour traiter à la fois , et . comme des points décimaux, vous devez non seulement remplacer l'un par l'autre, mais aussi vous assurer que la culture utilisée pour l'analyse syntaxique l'interprète comme un point décimal.

text = text.Replace(',', '.');
return double.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out value);

68voto

OliverAssad Points 11

Il n'est pas nécessaire de remplacer la virgule et le point.

J'ai eu le même problème. La raison en est simple : la culture de conversion joue un rôle important dans l'interprétation de la virgule ou du point. J'utilise une culture allemande où la virgule distingue les fractions, alors qu'ailleurs c'est le point qui fait l'affaire.

Ici, j'ai fait un exemple complet pour faire comprendre la différence.

string[] doubleStrings = {"hello", "0.123", "0,123"};
double localCultreResult;
foreach (var doubleString in doubleStrings)
{
    double.TryParse(doubleString, NumberStyles.Any, CultureInfo.CurrentCulture, out localCultreResult);
    Console.WriteLine(string.Format("Local culture results for the parsing of {0} is {1}", doubleString, localCultreResult));
}

double invariantCultureResult;
foreach (var doubleString in doubleStrings)
{
    double.TryParse(doubleString, NumberStyles.Any, CultureInfo.InvariantCulture, out invariantCultureResult);
    Console.WriteLine(string.Format("Invariant culture results for the parsing of {0} is {1}", doubleString, invariantCultureResult));
}

Les résultats sont les suivants : enter image description here

Jouez avec la culture et vous obtiendrez le résultat dont vous avez besoin.

27voto

mmdemirbas Points 3205

Vous voulez traiter le point ( . ) comme la virgule ( , ). Remplacer donc

if (double.TryParse(values[i, j], out tmp))

avec

if (double.TryParse(values[i, j].Replace('.', ','), out tmp))

19voto

Virtlink Points 12475

Le problème est que vous (ou le système) ne pouvez pas distinguer un séparateur de décimales d'un séparateur de milliers lorsqu'ils peuvent tous deux être une virgule ou un point. En voici un exemple :

Dans ma culture,

1.123 est une notation normale pour un nombre supérieur à 1000 ; alors que

1,123 est un nombre proche de 1.

L'utilisation de la culture invariante entraîne par défaut l'utilisation du point comme séparateur décimal. En général, vous devez vous assurer que tous les nombres sont écrits en utilisant la même culture constante sur tous les systèmes (par exemple, la culture invariante).

Si vous êtes sûr que vos nombres ne contiennent jamais rien d'autre qu'une virgule ou un point comme séparateur décimal (c'est-à-dire pas de séparateur de milliers), je vous conseille de ne pas utiliser de séparateur décimal. String.Replace() la virgule avec un point et faites le reste comme vous l'avez fait.

Dans le cas contraire, vous aurez du mal à programmer quelque chose qui permette de distinguer 1.123 de 1,123 sans en connaître la culture.

8voto

Sinipelto Points 93

Créez deux cultures statiques, l'une pour la virgule et l'autre pour le point.

    var commaCulture = new CultureInfo("en")
    {
        NumberFormat =
        {
            NumberDecimalSeparator = ","
        }
    };

    var pointCulture = new CultureInfo("en")
    {
        NumberFormat =
        {
            NumberDecimalSeparator = "."
        }
    };

Ensuite, utilisez chacun d'entre eux respectivement, en fonction de l'entrée (à l'aide d'une fonction) :

    public double ConvertToDouble(string input)
    {
        input = input.Trim();

        if (input == "0") {
            return 0;
        }

        if (input.Contains(",") && input.Split(',').Length == 2)
        {
            return Convert.ToDouble(input, commaCulture);
        }

        if (input.Contains(".") && input.Split('.').Length == 2)
        {
            return Convert.ToDouble(input, pointCulture);
        }

        throw new Exception("Invalid input!");
    }

Bouclez ensuite vos tableaux

    var strings = new List<string> {"0,12", "0.122", "1,23", "00,0", "0.00", "12.5000", "0.002", "0,001"};
    var doubles = new List<double>();

    foreach (var value in strings) {
        doubles.Add(ConvertToDouble(value));
    }

Cela devrait fonctionner même si l'environnement et la culture de l'hôte changent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X