Как мне округлить десятичное значение до 2 знаков после запятой (для вывода на страницу)

StackOverflow https://stackoverflow.com/questions/164926

  •  03-07-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

decimalVar.ToString ("#.##"); // returns "" when decimalVar == 0

или

decimalVar.ToString ("0.##"); // returns "0"  when decimalVar == 0

Другие советы

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

<Ол>
  • Не использовал округление банкиров
  • Не сохраняет значение как десятичное число.
  • Это то, что я бы использовал:

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

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

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

    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

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

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

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

    decimalVar.ToString("n2");
    

    Уже есть два ответа с высокими оценками, которые относятся к Decimal.Round (...), но я думаю, что требуется немного больше объяснений - потому что есть неожиданное важное свойство 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% вероятности, это потому, что это валюта, и в этом случае это, вероятно, хорошо для 95% времени:

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

    Или в XAML вы просто используете {Binding Price, StringFormat = c}

    В одном случае я столкнулся с необходимостью использования десятичной дробной части, так как десятичная дробь была при отправке XML на веб-сервис Amazon. Служба жаловалась, потому что десятичное значение (первоначально из SQL Server) было отправлено как 25.1200 и отклонено ( 25.12 было ожидаемым форматом).

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

     // This is an XML message - with generated code by XSD.exe
     StandardPrice = new OverrideCurrencyAmount()
     {
           TypedValue = Decimal.Round(product.StandardPrice, 2),
           currency = "USD"
     }
    

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

    Вот небольшая программа 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: <*>.00
    0.00: 0.00
    0.##: 0
    ===================
    ToString: 0.007
    c: <*>.01
    0.00: 0.01
    0.##: 0.01
    ===================
    

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

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

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

    Math.Round(exactResult * 1.00m, 2, MidpointRounding.AwayFromZero)
    
    6.665m.ToString() -> "6.67"
    
    6.6m.ToString() -> "6.60"
    

    Очень редко вы захотите пустую строку, если значение равно 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 минут времени (большинства) людей.

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

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

    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"));
    }
    

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

    Например:

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

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

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

    Ответ Майка М. был идеален для меня в .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);
    }
    

    https://msdn.microsoft. ком / EN-US / библиотека / dwhawy9k% 28В = vs.110% 29.aspx

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

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

    если вы хотите это для валюты, вы можете сделать это проще, набрав " C2 " вместо "F2"

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top