Як округлити десяткове значення до 2 знаків після коми (для виведення на сторінку)


649

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

Чи використовую .ToString()для цього варіацію ?

Відповіді:


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

або

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

31
проблема тут, коли у нас є 0,00; він повертає порожню рядок.
— Jronny

164
Тоді ви можете зробити decimalVar.ToString ("0. ##"). Ви також можете використовувати 0,00 як рядок форматування.
— Альбертейн

54
За допомогою цього рішення ви не матимете форматування культури, яке можна було б очікувати при читанні чисел. Для цього слід використовувати ToString ("N2") або ToString ("N").
— Shautieh

2
@Hill Decimaland Doubletype ToStringметод приймає аргумент для форматування. Спробуйте спочатку перетворити свою величину в десятковий / подвійний.
— sohaiby

1
@ f470071 Десяткові знаки - це типові значення і, як такі, ніколи не змінюються. Незважаючи на те, що від ToString () ніколи не очікувалося, що воно буде змінювати вміст того, до чого він викликається.
— Джастін Скілз

590

Я знаю, що це давнє запитання, але я був здивований, побачивши, що ніхто, схоже, не розмістив відповіді на це;

  1. Не використовували округлення банкірів
  2. Не зберегло значення як десяткове.

Це я б використовував:

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

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


3
ToString або string.Format не використовують округлення банкірів: msdn.microsoft.com/en-us/library/0c899ak8.aspx#sectionToggle1
— Matthijs Wessels

1
@MatthijsWessels Я знаю ... але це значення також не зберігається як десятковий.
— Майк М.

1
Це кращий спосіб по-справжньому представити два десяткових знаки, оскільки це не скине проміжні нулі.
— LiquidDrummer

355
decimalVar.ToString("F");

Це буде:

  • Закруглете до 2 знаків після коми, наприклад. 23.456→23.46
  • Переконайтесь, що завжди є 2 знаки після коми, наприклад. 23→ 23.00; 12.5→12.50

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

Ознайомтеся з документацією на ToString ("F") (завдяки Джону Шнайдеру).


10
Це чудово працює, коли лише 1 десятковий; .ToString ("#. ##") не вдається. Ця відповідь набагато краща
— Ерік Фрік

2
Чи не було б це навколо 23.456 => 23.46?
— rtpHarry

14
Документація про те, що означає "F" тут і як він працює: msdn.microsoft.com/en-us/library/…
— Джон Шнайдер,

4
Чому б не .ToString ("N") замість "F"? Наскільки я розумію, вони обидва будуть працювати для потреб цього питання, але N також поставить коси для цифр у тисячах.
— jgerman

Примітка. .Можливо, можна замінити ,на основі культури. Вам слід CultureInfo.InvariantCultureнадати другий аргумент, щоб вимкнути це.
— Дункан Лука

106

Якщо вам просто потрібно це для відображення, використовуйте 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


10
Технічно для десяткової суми це було б 123,4567 м, так? Без суфікса "m" - це подвійний
— Адам Теген

2
або ярлик $ "{значення: 0,00}"
— mamczas

56

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

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


4
@ Slick86 - точний знак
— fubo

48

Якщо ви хочете, щоб він був відформатований комами, а також десятковою комою (але не символом валюти), наприклад, 3,456,789.12 ...

decimalVar.ToString("n2");

1
Краще відповідь, оскільки питання стосувалося виведення на сторінку, а форматування чисел важливо для великих чисел. Також "n *" враховує нинішню культуру, тому вона може бути "3.456.789,12", "3 456 789,12" і т. Д.
— Shautieh

29

Уже є два відповіді на високу оцінку, які стосуються 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}

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

Все, що мені потрібно було зробити, - це Decimal.Round(...)2 знаки після коми, щоб вирішити проблему.

 // 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")і мені потрібно було його округлити і зберегти як decimal.


5
+1 це чудова відповідь. Коли ви говорите, що System.Decimal "знає, скільки є десяткових знаків" - термін полягає в тому, що System.Decimal не самонормалізується, як і інші типи плаваючої точки. Ще одна корисна властивість System.Decimal полягає в тому, що результати математичних операцій завжди мають найбільшу кількість десяткових знаків від вхідних аргументів, тобто. 1,0м + 2 000м = 3 000м . Ви можете використовувати цей факт, щоб змусити десятковий знак без десяткових знаків до 2 десяткових знаків, просто помноживши його на 1,00 м, наприклад. 10м * 1,00м = 10,00м .
— MattDavey

2
У MattDavey неправильно, додається десяткова точність. (1,0м * 1,00м) .ToString () = "1.000"
— Каїдо,

2
Дуже дуже корисно знати, що "Десяткова знає" скільки знаків після десяткових знаків залежно від місця її походження ". Дуже дякую!
— iheartcsharp

21

Ось невелика програма 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
===================

16

це не використовує заокруглення банкіра?
— Danimal

Це найкращий спосіб, тому що значення не перетворюється на рядок, і ви все ще можете виконувати математичні операції
— shinji14

@Danimal: Ви можете надати третій аргумент про зміну типу округлення
— Jay Sullivan

11

Дуже рідко ви хочете пусту рядок, якщо значення дорівнює 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 хвилин часу (більшість) людей.


1
в основному "#"означає цифру цифри (якщо потрібно) (без прокладки, якщо вона не потрібна) "0"означає цифру числа (не матер що) (
— заполнено

10

Відповідь Майка М. була ідеальною для мене в .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);
}

9

Нічого з цього не зробило саме те, що мені потрібно, щоб примусити 2 dp і округлити як0.005 -> 0.01

Примусовий 2 dp вимагає підвищення точності на 2 dp, щоб переконатися, що ми маємо принаймні 2 dp

то округлення, щоб переконатися, що у нас більше 2 дп

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

6.665m.ToString() -> "6.67"

6.6m.ToString() -> "6.60"

9

Відповідь з найвищою оцінкою описує метод форматування рядкового подання десяткового значення, і він працює.

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

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

7

Ви можете використовувати system.globalization для форматування номера в будь-якому необхідному форматі.

Наприклад:

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

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

Для отримання додаткової інформації перегляньте це посилання
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx


+1, але - об'єкт CultureInfo впливатиме лише на знак унікоду, який використовується для позначення десяткових знаків. напр. fr-FR буде використовувати кому замість крапки. Це не пов’язано з кількістю наданих десяткових знаків.
— MattDavey

4

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

Це посилання детально пояснює, як можна впоратися зі своєю проблемою та що ти можеш зробити, якщо хочеш дізнатися більше. Для простоти те, що ви хочете зробити

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

якщо ви хочете це для валюти, ви можете зробити це простіше, ввівши "C2" замість "F2"



1

Якщо вам потрібно зберегти лише два знаки після коми (тобто відрізати всі решта десяткових цифр):

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.