Разбор чисел с плавающей запятой: существует ли алгоритм Catch All? - PullRequest
60 голосов
/ 01 августа 2008

Одна из забавных частей мультикультурного программирования - числовые форматы.

  • Американцы используют 10000.50
  • немцы используют 10.000,50
  • Французский использовать 10 000,50

Мой первый подход состоял бы в том, чтобы взять строку, разобрать ее назад, пока я не столкнусь с разделителем, и использовать это как мой десятичный разделитель. В этом есть очевидный недостаток: 10.000 будет интерпретироваться как 10.

Другой подход: если строка содержит 2 разных нечисловых символа, используйте последний как десятичный разделитель и отбросьте остальные. Если у меня есть только один, проверьте, если это происходит более одного раза и сбросит его, если это произойдет. Если он появляется только один раз, проверьте, есть ли после него 3 цифры. Если да, откажитесь от него, в противном случае используйте его как десятичный разделитель.

Очевидным «лучшим решением» было бы определение культуры пользователя или браузера, но это не работает, если у вас есть француз, использующий Windows / браузер в США.

Содержит ли .NET Framework какой-то мифический парсер с плавающей запятой черной магии, который лучше, чем Double.(Try)Parse() при попытке автоматического определения формата чисел?

Ответы [ 4 ]

27 голосов
/ 02 августа 2008

Я думаю, что лучшее, что вы можете сделать в этом случае, это принять их мнение и показать им, что вы думаете, что они имели в виду. Если они не согласны, покажите им ожидаемый формат и попросите их ввести его снова.

26 голосов
/ 02 августа 2008

Я не знаю сторону проблемы ASP.NET, но у .NET есть довольно мощный класс: System.Globalization.CultureInfo . Вы можете использовать следующий код для разбора строки, содержащей двойное значение:

double d = double.Parse("100.20", CultureInfo.CurrentCulture);
//  -- OR --
double d = double.Parse("100.20", CultureInfo.CurrentUICulture);

Если ASP.NET каким-либо образом (т.е. используя заголовки HTTP-запроса) передает CultureInfo текущего пользователя либо в CultureInfo.CurrentCulture, либо в CultureInfo.CurrentUICulture, они будут работать нормально.

11 голосов
/ 02 августа 2008

Нельзя всем угодить. Если я введу десять как 10.000, а кто-то введет десять тысяч как 10.000, вы не сможете справиться с этим без некоторого знания культуры ввода. Как-то определите культуру (браузер, настройки системы - каков вариант использования? ASP? Внутреннее приложение или открыт для мира?), Или предоставьте пример ожидаемого форматирования, и используйте самый мягкий анализатор, который вы можете. Возможно что-то вроде:

double d = Double.Parse("5,000.00", NumberStyles.Any, CultureInfo.InvariantCulture);
9 голосов
/ 02 августа 2008

Разница между 12,345 на французском и английском языках составляет коэффициент 1000. Если вы укажете ожидаемый диапазон, где max <1000 * min, вы можете легко догадаться. </p>

Возьмем, например, рост человека (включая младенцев и детей) в мм.

Используя диапазон 200-3000, вход 1800 или 1800 можно однозначно интерпретировать как 1 метр и 80 сантиметров, тогда как вход 912.300 или 912,300 можно однозначно интерпретировать как 91 сантиметр и 2,3 миллиметра.

...