Як округлити десяткове значення до 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.45623.46
  • Переконайтесь, що завжди є 2 знаки після коми, наприклад. 2323.00; 12.512.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.