Как у меня может быть Десятичное число. TryParse анализируют 0.0?

Есть ли способ стать Десятичным. TryParse для парсинга строкового значения "0,0" или "00.00" или "000.000" как 0?

Я попробовал установку NumberStyles to Any.

8
задан Steven Sudit 26 January 2010 в 22:23
поделиться

10 ответов

Есть ли способ получить PECIMAL.Triparse для разбора строкового значения «0,0» или «00.00» или «000 000 000» Как 0?

Я интерпретирую ваш вопрос, чтобы означать. Скажем, я берут строки «0,0» , «00.00» и «000 000 000» ass DECIMAL.Triparse для их разбора. Когда я пишу результирующее десятичное значение к консоли, я вижу 0,0 , 0,00 и 0,000 соответственно. Есть ли способ получить penimal.triparse , чтобы вернуть десятичных случаев во всех этих случаях, которые будут записаны на консоль как 0 ?

нет. Подумайте, почему это должно быть. Типы десятичных представляют точные числа; В некоторых кругах 0,00 будет считаться более точным, чем 0,0 , который будет считаться более точным, чем 0 . Если PECIMAL.TRYPARSE укоренил, что точность, чем тип , типом не будет полезен для этих целей.

Это было достаточно легко, чтобы просто обрезать конечные нули перед вызовом Parse:

static char[] whitespaceAndZero = new[] {
    ' ',
    '\t',
    '\r',
    '\n',
    '\u000b', // vertical tab
    '\u000c', // form feed
    '0'
};
static string TrimEndWhitespaceAndZeros(string s) {
    return s.Contains('.') ? s.TrimEnd(whitespaceAndZero) : s;
}

static bool TryParseAfterTrim(string s, out decimal d) {
    return Decimal.TryParse(TrimEndWhiteSpaceAndZeros(s), out d);
}

Использование:

string s = "0.00";
decimal d;
TryParseAfterTrim(s, out d);
Console.WriteLine(d);

Выход:

0

Обратите внимание, что приведенное выше только показывает суть о том, как решить вашу проблему. Вам решать, есть ли и как вы собираетесь обрабатывать проблемы локализации. Как минимум, прежде чем вносить это в производство, вы должны рассмотреть возможность замены жесткокодируемых ». ' с CultureInfo.CurrentCulture.nomberformat.numberdecmaserSeparator . Вы должны рассмотреть вопрос о перегрузке TryparseavterTrim с одним и тем же списком параметров, как PECIMAL.Triparse . То есть:

bool TryParseAfterTrim(
    string s,
    NumberStyle style,
    IFormatProvider provider,
    out decimal result
)
5
ответ дан 5 December 2019 в 06:09
поделиться

Используя InvariantCulture, TryParse успешно интерпретирует все эти строки как ноль. Этот код, например:

decimal num = 66;
foreach (var str in new string[] { "0.0", "00.00", "000.000" })
{
    if (!decimal.TryParse(str, out num))
    {
        Console.WriteLine( "fail" );
    }
    Console.WriteLine(num);
}

Производит этот вывод:

0.0
0.00
0.000

Возможно, проблема в распечатке значений, а не в разборе? Если это так, то просто используйте строку форматирования, которая указывает, что десятичные разряды необязательны.

Console.WriteLine( num.ToString( "#0.#" ) );

Produces

0
0
0
13
ответ дан 5 December 2019 в 06:09
поделиться

Сохранение тяговых нулей в десятичных значениях было введено в .NET 1.1 для более строгого соответствия спецификацией CLI ECMA. См. Этот ответ на аналогичный вопрос .

В то время как оригинальный вопрос ограничивается удалением конечных нулей при разборке строки, я думаю, что важно понимать, почему и при каких обстоятельствах приземленных нулей сохраняется в внутреннем представлении десятичной ценности.

Призрачные нули могут появляться в десятичном значении в результате:

a) входного анализа, который имеет конечные нули, как в исходном посте или

b) в результате расчета. Например: Умножение десятичных значений 1.2 * 1.5 дает результат 1,80: это связано с тем, что умножение двух значений, которые каждый точны до одного десятичного времени, дает результат, который является точным до двух десятичных знаков - и поэтому второе десятичное число сохраняется, даже если его значение равно нулю.

Что делать о прохождении Zeroes во внутреннем десятичном представлении? В целом ничего не делайте: вы можете отформатировать на выходе на желаемое количество десятичных средств, поэтому они не повредит.

Десятичная десятка в основном используется для финансовых расчетов, и, как правило, желательно сохранить конечные нули, чтобы сумма округлая до ближайшего вента представлена ​​как 1.20, а не 1,2. Обычно при использовании десятичных средств вы будете работать на фиксированной точности (возможно, к ближайшему центру в розничной торговле или до ближайшей сотой цента при расчете платежи по использованию мобильных телефонов). Таким образом, ваша заявка на логике явно позаботится о закруглении до фиксированного числа десятичных знаков, используя явные правила округления, например, Налоговый расчет о том, что раунду до ближайшего вента, используя MidpointRounding.awyfromzero:

decimal price = 1.20M;   
decimal taxRate = 0.175; // 17.5%
decimal taxAmount = Math.Round(price*taxRate, 2, 
                      MidpointRounding.AwayFromZero);

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

Тем не менее, иногда может быть требование удаления задних нулей, сохраняя при этом все значимые цифры. AFAIK, нет встроенного метода для этого.

Если вам нужно сделать это, базовое решение будет форматироваться в виде строки с использованием строки стандартного формата «G28» (эквивалентной на пользовательскую строку формата «0. ############ ################ "), затем анализ результата обратно в десятичное число.

Альтернативный способ удаления задних нулей без преобразования в / из строки (вероятно, быстрее, хотя я не измерял его) - использовать Math.rund - E.g. Следующий метод:

    static decimal RemoveTrailingZeroes(decimal value)
    {
        const int MaxDecimals = 28;
        decimal roundedValue;
        for (int decimals = 0; decimals < MaxDecimals; decimals++)
        {
            roundedValue = Math.Round(value, decimals);
            if (value == roundedValue) return roundedValue;
        }
        return value;
    }
3
ответ дан 5 December 2019 в 06:09
поделиться

Что это не работает? Для меня это прекрасно работает (тестировалось с "0.0", "00.00" и "000.000"):

decimal d;
if (decimal.TryParse("0.0", NumberStyles.Any, CultureInfo.InvariantCulture, out d))
{
    // use d
}
2
ответ дан 5 December 2019 в 06:09
поделиться

// Это выводит 0, давая 0.0 в виде строки, хотя.....

 decimal d;

 decimal.TryParse("0.0", out d);

 string s = String.Format("{0:0}", d);
1
ответ дан 5 December 2019 в 06:09
поделиться

Почему вы не используете Int.triparse? или double.triparse?

1
ответ дан 5 December 2019 в 06:09
поделиться

В вашей консолье .Writeline нанесите строковый формат для поддержания двойной нулевой точности.

0
ответ дан 5 December 2019 в 06:09
поделиться

Я вижу, что вы имеете в виду. Следующий код:

decimal number = -1.0M;
bool res1 = decimal.TryParse("0.0", out number);
Console.WriteLine(string.Format("number = {0}", number));
number = -1.0M;
bool res2 = decimal.TryParse("00.00", out number);
Console.WriteLine(string.Format("number = {0}", number));
number = -1.0M;
bool res3 = decimal.TryParse("000.000", out number);
Console.WriteLine(string.Format("number = {0}", number));
number = -1.0M;
bool res4 = decimal.TryParse("0000.0000", out number);
Console.WriteLine(string.Format("number = {0}", number));

Отпечатки:

number = 0.0
number = 0.00
number = 0.000
number = 0.0000

, поэтому вход влияет на выход. Но проверка стоимости номера с использованием отладчика показывает «0» в окне подсказки и локальства, что указывает, что это проблема форматирования, а не фундаментальная проблема с сохраненным значением.

Однако, как и другие, говорили обрезать конечные нули (и десятичную точку) перед преобразованием.

0
ответ дан 5 December 2019 в 06:09
поделиться

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

Путь грубой силы будет вмешиваться со внутренней структурой десятичной структуры:

public static Decimal TrimFractionZeros(this Decimal zahl)
{
  int[] bits = decimal.GetBits(zahl);
  byte decimals = (Byte)(bits[3] >> 16);
  bool negativ = (bits[3] >> 31) != 0;
  zahl = new decimal(bits[0], bits[1], bits[2], false, 0);
  while ((decimals > 0) && ((zahl % 10) == 0))
  {
    zahl /= 10;
    decimals--;
  }
  bits = decimal.GetBits(zahl);
  return new decimal(bits[0], bits[1], bits[2], negativ, decimals);
}

не довольно быстро, но он изменит внутреннее представление «0,000» на «0» в десятичном периоде.

0
ответ дан 5 December 2019 в 06:09
поделиться

Я смиренно представляю это решение:

    decimal processedValue = value == 0 ? 0 : value;

Это не делает работу?

Вот полный пример:

string valueString = "0.000";
decimal value;
bool isValid = decimal.TryParse(valueString, out value);
if (isValid)
{
    decimal processedValue = value == 0 ? 0 : value;
    System.Diagnostics.Debug.Print("value: {0}, processedValue: {1}", value, processedValue);
}
2
ответ дан 5 December 2019 в 06:09
поделиться