Как отобразить десятичное значение с точностью до 2 знаков после запятой?

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

Могу ли я использовать для этого вариант .ToString()?


person wows    schedule 02.10.2008    source источник
comment
Здесь приведен краткий пример различных вариантов форматирования значений с плавающей запятой (выравнивание, количество цифр, разделители групп, экспонента, проценты, валюта и т. д.).   -  person saastn    schedule 02.03.2021


Ответы (16)


Я знаю, что это старый вопрос, но я был удивлен, увидев, что никто не опубликовал ответ на этот вопрос;

  1. Банковское округление не использовалось
  2. Не сохранял десятичное значение.

Вот что я бы использовал:

decimal.Round(yourValue, 2, MidpointRounding.AwayFromZero);

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

person Mike M.    schedule 20.04.2011
comment
ToString или string.Format не используйте банковское округление: msdn.microsoft. com / en-us / library / 0c899ak8.aspx # sectionToggle1 - person Matthijs Wessels; 21.03.2013
comment
@MatthijsWessels, я знаю ... но он также не сохраняет значение в виде десятичной дроби. - person Mike M.; 29.03.2013
comment
Это лучший способ по-настоящему представить два десятичных знака, поскольку при этом не будут отбрасываться нули в конце. - person LiquidDrummer; 22.04.2016

decimalVar.ToString("F");

Это будет:

  • Округлить до 2 десятичных знаков например. 23.45623.46
  • Убедитесь, что всегда есть 2 десятичных знака например. 2323.00; 12.512.50

Идеально подходит для отображения валюты.

Ознакомьтесь с документацией по ToString ("F ") (спасибо Джону Шнайдеру).

person Sofox    schedule 15.12.2009
comment
Это отлично работает, когда есть только 1 десятичный знак; .ToString (#. ##) не работает. Этот ответ намного лучше - person Eric Frick; 21.03.2013
comment
Разве не было бы 23,456 = ›23,46? - person rtpHarry; 31.05.2013
comment
Документация о том, что здесь означает буква F и как это работает: msdn.microsoft.com/en-us/library/ - person Jon Schneider; 25.06.2014
comment
Почему бы не использовать .ToString (N) вместо F? Насколько я понимаю, они оба будут работать для нужд этого вопроса, но N также будет ставить запятые для чисел в тысячах. - person jgerman; 29.09.2014
comment
Примечание. . можно заменить на , в зависимости от культуры. Вы должны передать CultureInfo.InvariantCulture в качестве второго аргумента, чтобы отключить это. - person Duncan Luk; 12.02.2019

Если вам это просто нужно для отображения, используйте string.Format

String.Format("{0:0.00}", 123.4567m);      // "123.46"

http://www.csharp-examples.net/string-format-double/

«M» - это десятичный суффикс. О десятичном суффиксе:

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

person Jorge Ferreira    schedule 02.10.2008
comment
Технически, для десятичной дроби это будет 123,4567 м, да? Без суффикса m это двойное - person Adam Tegen; 30.11.2009
comment
или ярлык $ {value: 0.00} - person mamczas; 21.11.2018

Для десятичного d = 12,345; выражения d.ToString ("C") или String.Format ("{0: C}", d) yield $ 12,35 - обратите внимание, что используются текущие настройки валюты, включая символ.

Обратите внимание, что "C" использует количество цифр из текущего языка и региональных параметров. Вы всегда можете изменить значение по умолчанию, чтобы добиться необходимой точности с помощью C{Precision specifier}, например String.Format("{0:C2}", 5.123d).

person Hafthor    schedule 02.10.2008
comment
@ Slick86 - актуальный знак - person fubo; 29.05.2015

Если вы хотите, чтобы он был отформатирован запятыми, а также десятичной точкой (но без символа валюты), например 3,456,789,12 ...

decimalVar.ToString("n2");
person Joel Mueller    schedule 21.04.2009
comment
Лучший ответ, так как вопрос касался вывода на страницу, а форматирование чисел важно для больших чисел. Кроме того, n * учитывает текущую культуру, поэтому это может быть 3,456,789,12, 3 456 789,12 и т. Д. - person Shautieh; 21.08.2014

Есть очень важная характеристика Decimal, которая не очевидна:

Decimal "знает", сколько десятичных знаков в нем, в зависимости от того, откуда оно взялось.

Следующее может быть неожиданным:

Decimal.Parse("25").ToString()          =>   "25"
Decimal.Parse("25.").ToString()         =>   "25"
Decimal.Parse("25.0").ToString()        =>   "25.0"
Decimal.Parse("25.0000").ToString()     =>   "25.0000"

25m.ToString()                          =>   "25"
25.000m.ToString()                      =>   "25.000"

Выполнение тех же операций с Double приведет к нулю десятичных знаков ("25") для всех приведенных выше примеров.

Если вы хотите использовать десятичную дробь до двух знаков после запятой, высока вероятность того, что это валюта, и в этом случае это, вероятно, нормально в 95% случаев:

Decimal.Parse("25.0").ToString("c")     =>   "$25.00"

Или в XAML вы использовали бы {Binding Price, StringFormat=c}

Я столкнулся с одним случаем, когда мне понадобилось десятичное число AS a decimal, когда я отправлял XML в веб-сервис Amazon. Служба жаловалась, потому что десятичное значение (первоначально из SQL Server) было отправлено как 25.1200 и отклонено (25.12 был ожидаемым форматом).

Все, что мне нужно было сделать, это Decimal.Round(...) с двумя десятичными знаками, чтобы решить проблему независимо от источника значения.

 // generated code by XSD.exe
 StandardPrice = new OverrideCurrencyAmount()
 {
       TypedValue = Decimal.Round(product.StandardPrice, 2),
       currency = "USD"
 }

TypedValue относится к типу Decimal, поэтому я не мог просто сделать ToString("N2"), и мне нужно было округлить его и оставить как decimal.

person Simon_Weaver    schedule 26.10.2011
comment
+1 это отличный ответ. Когда вы говорите, что System.Decimal знает, сколько десятичных знаков имеет, это означает, что System.Decimal не самонормализуется, как другие типы с плавающей запятой. Еще одно полезное свойство System.Decimal заключается в том, что результат математических операций всегда имеет наибольшее количество десятичных знаков из входных аргументов, т.е. 1,0 м + 2 000 м = 3 000 м. Вы можете использовать этот факт, чтобы преобразовать десятичную дробь без десятичных знаков в 2 десятичных разряда, просто умножив ее на 1,00 м, например. 10 м * 1,00 м = 10,00 м. - person MattDavey; 10.01.2012
comment
MattDavey неверен, добавлена ​​десятичная точность. (1,0 м * 1,00 м) .ToString () = 1.000 - person Kaido; 25.10.2012
comment
Очень, очень полезно знать, что десятичная дробь «знает», сколько десятичных знаков она имеет, в зависимости от того, откуда она взялась. Большое спасибо! - person iheartcsharp; 08.07.2013
comment
ценю ваш ответ и объяснение! - person sspaniel; 28.01.2021

Вот небольшая программа Linqpad для отображения разных форматов:

void Main()
{
    FormatDecimal(2345.94742M);
    FormatDecimal(43M);
    FormatDecimal(0M);
    FormatDecimal(0.007M);
}

public void FormatDecimal(decimal val)
{
    Console.WriteLine("ToString: {0}", val);
    Console.WriteLine("c: {0:c}", val);
    Console.WriteLine("0.00: {0:0.00}", val);
    Console.WriteLine("0.##: {0:0.##}", val);
    Console.WriteLine("===================");
}

Вот результаты:

ToString: 2345.94742
c: $2,345.95
0.00: 2345.95
0.##: 2345.95
===================
ToString: 43
c: $43.00
0.00: 43.00
0.##: 43
===================
ToString: 0
c: $0.00
0.00: 0.00
0.##: 0
===================
ToString: 0.007
c: $0.01
0.00: 0.01
0.##: 0.01
===================
person What Would Be Cool    schedule 18.11.2013

Math.Round Method (Decimal, Int32)

person John Smith    schedule 02.10.2008
comment
это не использует банковское округление? - person Danimal; 03.10.2008
comment
Это лучший способ, потому что значение не преобразуется в строку, и вы все равно можете выполнять математические операции. - person shinji14; 21.06.2010
comment
@Danimal: вы можете указать третий аргумент, чтобы изменить тип округления - person Jay Sullivan; 29.07.2013

Очень редко вам нужна пустая строка, если значение равно 0.

decimal test = 5.00;
test.ToString("0.00");  //"5.00"
decimal? test2 = 5.05;
test2.ToString("0.00");  //"5.05"
decimal? test3 = 0;
test3.ToString("0.00");  //"0.00"

Ответ с наивысшей оценкой неверен и потратил 10 минут (большинства) людей впустую.

person goamn    schedule 01.08.2017
comment
в основном "#" означает цифру числа (при необходимости) (без заполнения, если не требуется) "0" означает цифру числа (не важно, что) (с нулями, если недоступно) - person Mr Heelis; 19.01.2018

Ответ Майка М. был идеальным для меня в .NET, но в .NET Core в то время не было метода decimal.Round письма.

В .NET Core мне пришлось использовать:

decimal roundedValue = Math.Round(rawNumber, 2, MidpointRounding.AwayFromZero);

Хакерский метод, включая преобразование в строку, это:

public string FormatTo2Dp(decimal myNumber)
{
    // Use schoolboy rounding, not bankers.
    myNumber = Math.Round(myNumber, 2, MidpointRounding.AwayFromZero);

    return string.Format("{0:0.00}", myNumber);
}
person HockeyJ    schedule 14.10.2016

Ни один из них не сделал в точности того, что мне было нужно, чтобы вызвать 2 d.p. и округлить до 0.005 -> 0.01

Форсирование 2 д.п. требует увеличения точности на 2 п.п. чтобы у нас было не менее 2 д.п.

затем округляем, чтобы убедиться, что у нас не более 2 d.p.

Math.Round(exactResult * 1.00m, 2, MidpointRounding.AwayFromZero)

6.665m.ToString() -> "6.67"

6.6m.ToString() -> "6.60"
person Kaido    schedule 25.10.2012

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

Однако, если вы действительно хотите изменить точность, сохраненную до фактического значения, вам нужно написать что-то вроде следующего:

public static class PrecisionHelper
{
    public static decimal TwoDecimalPlaces(this decimal value)
    {
        // These first lines eliminate all digits past two places.
        var timesHundred = (int) (value * 100);
        var removeZeroes = timesHundred / 100m;

        // In this implementation, I don't want to alter the underlying
        // value.  As such, if it needs greater precision to stay unaltered,
        // I return it.
        if (removeZeroes != value)
            return value;

        // Addition and subtraction can reliably change precision.  
        // For two decimal values A and B, (A + B) will have at least as 
        // many digits past the decimal point as A or B.
        return removeZeroes + 0.01m - 0.01m;
    }
}

Пример модульного теста:

[Test]
public void PrecisionExampleUnitTest()
{
    decimal a = 500m;
    decimal b = 99.99m;
    decimal c = 123.4m;
    decimal d = 10101.1000000m;
    decimal e = 908.7650m

    Assert.That(a.TwoDecimalPlaces().ToString(CultureInfo.InvariantCulture),
        Is.EqualTo("500.00"));

    Assert.That(b.TwoDecimalPlaces().ToString(CultureInfo.InvariantCulture),
        Is.EqualTo("99.99"));

    Assert.That(c.TwoDecimalPlaces().ToString(CultureInfo.InvariantCulture),
        Is.EqualTo("123.40"));

    Assert.That(d.TwoDecimalPlaces().ToString(CultureInfo.InvariantCulture),
        Is.EqualTo("10101.10"));

    // In this particular implementation, values that can't be expressed in
    // two decimal places are unaltered, so this remains as-is.
    Assert.That(e.TwoDecimalPlaces().ToString(CultureInfo.InvariantCulture),
        Is.EqualTo("908.7650"));
}
person Alex    schedule 24.08.2017

Вы можете использовать system.globalization для форматирования числа в любом требуемом формате.

Например:

system.globalization.cultureinfo ci = new system.globalization.cultureinfo("en-ca");

Если у вас есть decimal d = 1.2300000, и вам нужно обрезать его до двух знаков после запятой, его можно напечатать следующим образом d.Tostring("F2",ci);, где F2 - это строка, форматируемая до двух знаков после запятой, а ci - это локаль или информация о культуре.

для получения дополнительной информации перейдите по этой ссылке
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx

person Smitha Poluri    schedule 23.08.2011
comment
+1, но - объект CultureInfo будет влиять только на символ Юникода, используемый для обозначения десятичного разряда. например. fr-FR будет использовать запятую вместо точки. Это не связано с количеством отображаемых десятичных знаков. - person MattDavey; 11.01.2012

https://msdn.microsoft.com/en-us/library/dwhawy9k%28v=vs.110%29.aspx

Эта ссылка подробно объясняет, как вы можете решить свою проблему и что вы можете сделать, если хотите узнать больше. Для простоты вам нужно

double whateverYouWantToChange = whateverYouWantToChange.ToString("F2");

если вы хотите получить это для валюты, вы можете упростить задачу, набрав «C2» вместо «F2».

person Jeff Jose    schedule 25.06.2016

Если вам нужно оставить только 2 десятичных разряда (т.е. обрезать все остальные десятичные цифры):

decimal val = 3.14789m;
decimal result = Math.Floor(val * 100) / 100; // result = 3.14

Если вам нужно сохранить только 3 десятичных знака:

decimal val = 3.14789m;
decimal result = Math.Floor(val * 1000) / 1000; // result = 3.147
person Aleksei Mialkin    schedule 13.03.2020

person    schedule
comment
проблема здесь в том, что у нас 0,00; он возвращает пустую строку. - person Jronny; 04.05.2010
comment
Затем вы можете сделать decimalVar.ToString (0. ##). Вы также можете использовать 0,00 в качестве строки форматирования. - person albertein; 04.05.2010
comment
@MikeCole Я не думаю, что вы можете выполнить усечение с помощью одного только форматирования - единственный известный мне способ - сначала передать его в Math.Floor, например, (Math.Floor (decimalVar * 100M) / 100M) .ToString ( 0.00) должен работать (и если вы используете двойные, а не десятичные дроби, используйте, конечно, 100D вместо 100M). - person BrainSlugs83; 26.08.2013
comment
С этим решением у вас не будет форматирования культуры, которое можно было бы ожидать при чтении чисел. Для этого вы должны использовать ToString (N2) или ToString (N). - person Shautieh; 21.08.2014
comment
Это очень вводящий в заблуждение ответ. Это просто создает новую строку, но числовое значение остается неизменным. Это создает хаос в любом другом месте, где используется это количество. Это серьезная проблема, не позволяющая понизить десятичную версию типа до некоторого количества десятичных знаков. - person f470071; 02.10.2015
comment
Метод @Hill Decimal и Double type ToString принимает аргумент для форматирования. Попробуйте сначала преобразовать ваше значение в десятичное / двойное. - person sohaiby; 13.03.2016
comment
@ f470071 Десятичные дроби - это типы значений, поэтому они никогда не изменяются. Тем не менее, от ToString () никогда не ожидалось, что он изменит содержимое того, что вызвано. - person Justin Skiles; 26.08.2016
comment
Работает нормально для десятичных знаков. Если это целое число, то #. ## будет игнорировать десятичные знаки. Однако {0: #, ## 0.00} будет работать как для десятичных, так и для целых чисел. - person Rahatur; 03.10.2016
comment
@Hill Вы можете получить эту ошибку с типом, допускающим значение NULL. Попробуйте yourNumber.Value.ToString (0. ##), чтобы решить вашу проблему. - person Anh Hoang; 05.04.2018
comment
Приведенное ниже решение лучше, поскольку оно рассматривает его как десятичное и возвращает десятичное. - person Mocas; 23.01.2019