2010-03-30 3 views
15

Короткий и сладкий вариант:decimal.TryParse() падает ведущий «1»

На одной машине из около ста испытательных машин decimal.TryParse() является преобразование «1,01» 0,01


Хорошо, это будет звучать безумно, но неся со мной ...

У нас есть клиентские приложения, которые общаются с веб-сервисом через JSON, и эта служба возвращает десятичное значение в виде строки, поэтому мы сохраняем его как строку в нашем объекте модели:

[DataMember(Name = "value")] 
public string Value { get; set; } 

Когда мы отображаем это значение на экране, оно отформатируется на определенное количество знаков после запятой. Таким образом, мы используем строку -> десятичную, затем десятичную -> строку.

Приложение в настоящее время проходит окончательное тестирование и работает на более чем 100 машинах, где все это работает нормально. Однако на одна машина, если десятичное значение имеет ведущее «1», то оно заменяется нулем. Я добавил простой протоколирование в коде так это выглядит следующим образом:

Log("Original string value: {0}", value); 
decimal val; 
if (decimal.TryParse(value, out val)) 
{ 
    Log("Parsed decimal value: {0}", val); 
    string output = val.ToString(format, CultureInfo.InvariantCulture.NumberFormat); 
    Log("Formatted string value: {0}", output); 
    return output; 
} 

На моей машине - любой каждый клиентский компьютер - выход файл_журнала является:

  • Оригинал строковое значение: 1,010000
  • Проанализированное десятичное значение: 1,010000
  • Форматированные строковое значение: 1,01

На неисправной машине выход:

  • Оригинал строковое значение: 1,010000
  • Успешно разобран десятичное значение: 0,010000
  • отформатированный строковое значение: 0,01

Так это что метод decimal.TryParse виноват.

Вещи, которые мы уже пробовали:

  • Удаление и повторная установка клиентского приложения
  • Удаление и повторная установка .NET 3.5 sp1
  • Сравнение региональных параметров дефектной аппарата для чисел (с использованием английского языка (United Kingdom)) к работающим машинам - никаких различий.

Кто-нибудь видел что-нибудь подобное или имеет какие-либо предложения? Я быстро иссякают идеи ...


В то время как я печатал это еще некоторая информация пришла: Передача строковое значение «10000» для преобразования.ToInt32() возвращает 0, так что и, кажется, падение ведущих 1.


Дальнейшие тесты, основанные на комментарии:

  • 1,01 -> 0,01
  • 111,01 -> 11,01
  • 123.01 -> 23,01
  • 231,01 -> 231,01
  • 01,01 -> 1,01

Таким образом, похоже, что это влияет только на 1 и только в том случае, если они являются первым символом строки. Очень странно, но, по крайней мере, это непротиворечиво.

+1

Weird. Что происходит с другими цифрами типа «123» или «321»? –

+0

Плохое ОЗУ в машине? Вы пытались запустить что-то вроде memtest86? –

+0

Это действительно плохая идея, но если вы предварительно набрали нуль ...? – spender

ответ

16

Я могу воспроизвести ваши результаты. Рассмотрим:

public NumberFormatInfo OneIsPositiveSignFormat() 
{ 
    NumberFormatInfo custom = new NumberFormatInfo(); 
    custom.PositiveSign = "1"; 
    return custom; 
} 

И потом:

if (decimal.TryParse(value, NumberStyles.Number, OneIsPositiveSignFormat(), out val)) 

Дело в том: региональные настройки не показывает вам текущий положительный знак, и в основном вы не установили культуру при анализе числа ,

Значение может поступать из различных мест: Это может исходить из реестра в качестве системы по умолчанию, или по умолчанию может быть установлено кодом:

CultureInfo customCulture = (CultureInfo)CultureInfo.InvariantCulture.Clone(); 
customCulture.NumberFormat = OneIsPositiveSignFormat(); 
Thread.CurrentThread.CurrentCulture = customCulture; 
+1

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

+2

И у нас есть победитель! Просто запустил следующий код на своей машине: Console.WriteLine (System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PositiveSign); и он выводит «1». Теперь просто нужно выяснить, как это изменить ... –

+0

Уверен, что это была сторонняя программа, которая сделала это. Какое чудовище. – Kugel

-1

посмотреть, как региональные настройки установлены для этого компьютера, возможно, это «.». устанавливается как разделитель тысяч не как десятичный разделитель. Попробуйте использовать Decimal.TryParse (String, NumberStyles, IFormatProvider, out Decimal val) и передать NumberFormatInfo, созданную с десятичным разделителем "."

+2

OP уже сказал, что в региональных настройках нет различий - плюс, если 1.000 был введен, когда '.' был тысячным разделителем, он дал бы 1000, а не 0. –