Десятичная ошибка преобразования ToString() в С#

У меня возникла проблема, когда я пытаюсь преобразовать decimal? в string. Сценарий

decimal decimalValue = .1211;
string value = (decimalValue * 100).ToString();

Текущий результат: value = 12.1100

Ожидаемый результат: value = 12.11

Пожалуйста, дайте мне знать, что может быть причиной этого.

Ответы

Ответ 1

Decimal сохраняет любые конечные нули в числе Decimal. Если вы хотите вместо двух десятичных знаков:

decimal? decimalValue = .1211m;
string value = ((decimal)(decimalValue * 100)).ToString("#.##")

http://msdn.microsoft.com/en-us/library/0c899ak8.aspx

или

string value = ((decimal)(decimalValue * 100)).ToString("N2")

http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx

Из System.Decimal:

Десятичное число является плавающей точкой значение, которое состоит из знака, числовое значение, где каждая цифра в значение находится в диапазоне от 0 до 9, а a коэффициент масштабирования, который указывает положение плавающей десятичной точки который отделяет интеграл и дробные части числового значения.

Двоичное представление десятичной Значение состоит из 1-битового знака, 96-битное целочисленное число и масштабирование фактор, используемый для деления 96-битного целое число и указать, какая часть его является десятичной дробью. Масштабирование фактор неявно равен числу 10, повышен до уровня от 0 до 28. Следовательно, двоичный представление десятичного значения формы ((-2 96 до 2 96)/10 (от 0 до 28)), где -2 96 -1 равно MinValue и 2 96 -1 равно MaxValue.

Масштабный коэффициент также сохраняет любые конечные нули в десятичном числе. Конечные нули не влияют на значение десятичного числа в арифметические операции или операции сравнения. Однако → конечные нули могут быть обнаруженный методом ToString, если соответствующая строка формата применяется <

Примечания:

  • десятичное умножение нужно отличить до десятичного, потому что Nullable<decimal>.ToString не имеет поставщика формата
  • как сказал Крис, вам нужно обработать случай, когда Nullable<decimal> равен null. Один из способов: Null-Coalescing-Operator:

    ((decimal)(decimalValue ?? 0 * 100)).ToString("N2")
    

Эта статья от Джона Скита стоит прочитать:

Десятичная с плавающей запятой в .NET (для сохранения нулей, если вы нетерпеливы)

Ответ 2

Поскольку вы используете Nullable<T> как ваш decimal, Nullable<T>.ToString(), метод не имеет перегрузки, он принимает параметры, которые можно использовать для форматирования.

Вместо этого вы можете явно применить его к decimal, и вы можете использовать метод .ToString() для форматирования.

Просто используйте формат "0.00" в методе .ToString().

decimal? decimalValue = .1211M;
string value = ((decimal)(decimalValue * 100)).ToString("0.00");
Console.WriteLine(value);

Выход будет:

12.11

Вот DEMO.

В качестве альтернативы вы можете использовать Nullable<T>.Value без какой-либо разговора:

string value = (decimalValue * 100).Value.ToString("0.00");

За дополнительной информацией обращайтесь Custom Numeric Format Strings

Ответ 3

В качестве альтернативы вы можете указать формат "F2", например: string val = decVal.ToString("F2"), поскольку это указывает на 2 десятичных знака.

Ответ 4

Используйте спецификатор формата с фиксированной точкой ( "F" .

   string value = (decimalValue * 100).ToString("F");

Спецификатор точности по умолчанию основан на значении свойства NumberFormatInfo.NumberDecimalDigits, которое по умолчанию имеет значение 2. Поэтому, если не указать цифру aftyer "F", она по умолчанию указывает две десятичные цифры.

F0 - No decimal places
F1 - One decimal place

Ответ 5

String.Format("{0:0.00}", decimalValue * 100);

Вы можете использовать .Format() в качестве альтернативы .ToString("0.00").

Ответ 6

Так как decimal? не имеет перегрузки ToString(string format), проще всего использовать String.Format вместо этого, который также обеспечит согласованные результаты с тегом null для decimalValue (в результате получается пустая строка) по сравнению с исходным кодом:

string value = String.Format("{0:#.##}", decimalValue * 100);

Но есть и другие соображения для других чисел, о которых вы не поняли.

Если у вас есть число, которое не производит значение больше 0, показывает ли он ноль? То есть, для 0.001211 отображается ли оно как 0.12 или .12? Если вам нужен начальный ноль, используйте это вместо этого (обратите внимание на изменение от #.## до 0.##):

string value = String.Format("{0:0.##}", decimalValue * 100);

Если у вас более двух значащих знаков после запятой, вы хотите, чтобы они отображались? Итак, если у вас .12113405 будет отображаться как 12.113405? Если это так, используйте:

string value = String.Format("{0:#.############}", decimalValue * 100);

(честно говоря, я думаю, что должна быть лучшая строка форматирования, особенно, поскольку она поддерживает только 12 знаков после запятой)

И, конечно, если вы хотите как ведущие нули, так и несколько десятичных знаков, просто соедините два выше:

string value = String.Format("{0:0.############}", decimalValue * 100);

Ответ 7

Если вы не хотите ограничивать определенное количество десятичных цифр:

decimal? decimalValue = .1211;
string value = decimalValue == null 
               ? "0"
               : decimalValue == 0
               ? "0"
               : (decimalValue * 100).ToString().TrimEnd('0');

Это обрезает любые (если есть) конечные нули строки, а также возвращает "0", если decimalValue равно null. Если значение равно 0, то "0" возвращается без обрезки.