Двойные значения TryParse

Мне нужно проверить двойные значения. Когда я TryParse .00 or ,00 возвращаю false, но я допускаю, что эти значения должны быть истинными.

Этот код не работает правильно для этого случая

модель = ,00 или .002 или ,789 или .12 ...

double number;
double.TryParse(model, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out number)

person zrabzdn    schedule 14.02.2014    source источник
comment
Почему бы вам не прочитать документацию?   -  person Andreas    schedule 14.02.2014
comment
Запуск этого ".00" успешно анализирует 0, а ",00" возвращает false.   -  person asawyer    schedule 14.02.2014
comment
Мне нужно ,00 вернуть true также   -  person zrabzdn    schedule 14.02.2014
comment
@DStanley NumberFormatInfo.InvariantInfo означает независимость от культуры, не так ли?   -  person asawyer    schedule 14.02.2014
comment
@asawyer да, извините - сначала не увидел эту часть.   -  person D Stanley    schedule 14.02.2014
comment
@zrabzdn что должен вернуть 12.345,67? Как насчет 123,456?   -  person D Stanley    schedule 14.02.2014
comment
Что делать, если "1.001" передается? А 1001? Откуда вы знаете, действительно ли одно из них означает тысячу и один или одну и одну тысячную?   -  person Jon Senchyna    schedule 14.02.2014
comment
@asawyer, нет, это не зависит от культуры. Он использует встроенную настройку культуры, которая отличается. Он использует . в качестве десятичного разделителя.   -  person Silvermind    schedule 14.02.2014
comment
@Silvermind О, хорошо. Спасибо за информацию.   -  person asawyer    schedule 14.02.2014


Ответы (3)


Вы можете зациклить все поддерживаемые культуры:

bool parsable = false;
double number = 0;
var supportedCultures = new[] { CultureInfo.InvariantCulture, CultureInfo.CreateSpecificCulture("de-DE") };
foreach(var culture in supportedCultures)
{
    parsable = double.TryParse(model, NumberStyles.Any, culture, out number);
    if (parsable)
        break;
}

или с LINQ:

CultureInfo thisCulture = supportedCultures
    .FirstOrDefault(c => double.TryParse(model, NumberStyles.Any, c, out number));
if (thisCulture != null)
{
    Console.WriteLine("Number was parsable to " + number);
}

старый подход, слишком подверженный ошибкам, как указал asawyer ("1,000,000.00"):

Вы можете заменить запятые точками:

bool parsable = double.TryParse(model.Replace(",", "."), NumberStyles.Any, NumberFormatInfo.InvariantInfo, out number);

person Tim Schmelter    schedule 14.02.2014
comment
Как "1,000,000.00" будет анализировать это изменение? - person asawyer; 14.02.2014
comment
Замена строки — это грязный и потенциально сломанный хак. Циклический просмотр культур, которые вы хотите поддерживать, является правильным подходом, поскольку именно это подразумевает синтаксический анализ как .00, так и ,00. - person Yuck; 14.02.2014
comment
@asawyer: я удалил этот подход, так как он действительно подвержен ошибкам. - person Tim Schmelter; 14.02.2014
comment
@TimSchmelter SortedList тоже может быть хорошим улучшением, поскольку OP может указать, какие культуры следует попробовать в первую очередь. - person Yuck; 14.02.2014
comment
@Yuck: Но он мог бы использовать и обычный список, так как FirstOrDefault (или цикл) прервется при первом совпадении, поэтому культура с наименьшим индексом. - person Tim Schmelter; 14.02.2014

Когда вы используете NumberFormatInfo.InvariantInfo, вы заставляете синтаксический анализатор обрабатывать . как десятичный разделитель, а , как разделитель тысяч. Так

double.TryParse(".002", out number)

вернет true, но

double.TryParse(",789", out number)

не будет.

Если вы хотите поддерживать несколько форматов, вам придется вызывать TryParse для каждого формата. Нет способа попытаться проанализировать число, которое было бы допустимым в формате, потому что они могут возвращать другое значение. "123,456" можно было интерпретировать двумя разными способами в зависимости от того, какую культуру вы использовали.

person D Stanley    schedule 14.02.2014

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

Например, что если передать "1.001"? А как насчет "1,001"? Откуда вы знаете, действительно ли одно из них означает «тысяча и один» или «одна и одна тысячная»?

person Jon Senchyna    schedule 14.02.2014