2016-01-27 7 views
7

Я испытываю странное поведение при преобразовании числа в double при использовании информации о культуре.
При преобразовании "3,3" с использованием голландской культуры обрабатывается правильно. Если я конвертирую "3,3" с использованием культуры США, он возвращает 33. Я ожидал ошибки. См. Мой пример:Число с десятичным разделителем, неправильно введенным в Double

static void Main(string[] args) 
{ 
    CultureInfo cultureDutch = new CultureInfo("nl-NL"); 
    CultureInfo cultureUS = new CultureInfo("en-US"); 

    System.Threading.Thread.CurrentThread.CurrentCulture = cultureDutch; 
    Console.WriteLine("Input 3,3 --> Expected 3,3"); 
    Console.WriteLine("Output = " + Convert.ToDouble("3,3", cultureDutch)); 
    // Actual result --> 3,3 

    Console.WriteLine("Input 3,3 --> Expected InvalidCastException"); 
    Console.WriteLine("Output = " + Convert.ToDouble("3,3", cultureUS)); 
    // Actual result --> 33 

    Console.WriteLine(); 
    Console.WriteLine(); 

    System.Threading.Thread.CurrentThread.CurrentCulture = cultureUS; 
    Console.WriteLine("Input 3.3 --> Expected InvalidCastException"); 
    Console.WriteLine("Output = " + Convert.ToDouble("3.3", cultureDutch)); 
    // Actual result --> 33 

    Console.WriteLine("Input 3.3 --> Expected 3.3"); 
    Console.WriteLine("Output = " + Convert.ToDouble("3.3", cultureUS)); 
    // Actual result --> 3.3 
    Console.ReadLine(); 
} 

Каков правильный способ справиться с этим? Я предпочел бы исключение, если разделитель десятичных (или тысяч) недействителен.

+0

Эта запятая является разделителем тысяч, .NET не придирчивы к тому, где ее ставит пользователь. Или что у пользователя неправильная картина, как это делают индийцы. Вам нужно продолжить реальное исправление и узнать, на каком языке говорит пользователь. Это никогда не является реальной проблемой, это Thread.CurrentCulture. У вас есть только эта проблема, когда вы говорите по-голландски и притворяетесь не из Голландии, не сообщая об этом ОС. –

ответ

0

Вместе с ответом Боаса Энклера я смог решить проблему. Поэтому сначала я сканирую вход для тысяч разделителей, исходя из текущей культуры. И, наконец, я проанализирую входное значение на двойной.

private static string RemoveThousandSeparator(string input) 
    { 
     Regex removeThousandSeparatorExpr = new Regex(@"^-?(?:\d+|\d{1,3}(?:\" 
         + <CultureInfo>.NumberGroupSeparator + @"\d{3})+)(?:\" 
         + <CultureInfo>.NumberDecimalSeparator + @"\d+)?$"); 
     Match match = removeThousandSeparatorExpr.Match(input); 
     if (match.Success) 
     { 
      input = input.Replace(<CultureInfo>.NumberGroupSeparator, ""); 
     } 
     else 
     { 
      throw new Exception("Invalid input value"); 
     } 

     return input; 
    } 
2

Если вы просто хотите, чтобы разобрать его, я хотел бы использовать выделенные методы синтаксического анализа, в котором вы можете установить NumberStyles

Следующий код будет бросить FormatException

var culture =new CultureInfo("en-US"); 
var result = double.Parse("3,3", NumberStyles.AllowDecimalPoint, culture); 

Для получения дополнительной информации см Double.Parse Method

+0

Я думал, что это был ответ, но, к сожалению, это не так. Поскольку вход может содержать как десятичные, так и тысячи разделителей, запрещающие тысячи разделителей, не является ответом. В культуре США 1000.0 является правильной, но с использованием AllowDecimalPoint считается недействительным. Я думаю, мне нужно регулярное выражение для разделения тысяч разделителей, прежде чем использовать значения в вычислениях. –