C # Double - форматування ToString () з двома знаками після коми, але без округлення


153

Як я відформатую а Doubleдо а Stringв C #, щоб було лише два десяткових знаки?

Якщо я використовую String.Format("{0:0.00}%", myDoubleValue)число, то він округляється, і я хочу простий укорочений без будь-якого округлення. Я також хочу, щоб перетворення Stringбуло чутливим до культури.


Що ви маєте на увазі під "культурольотом"? Чи означає це, що результат форматування повинен змінюватися залежно від значення культури, наданої програмістом? Або ви хочете використовувати будь-яку культуру за замовчуванням для поточного потоку?
CesarGon

Відповіді:


204

Я використовую наступне:

double x = Math.Truncate(myDoubleValue * 100) / 100;

Наприклад:

Якщо число 50,947563 і ви використовуєте наступне, станеться наступне:

- Math.Truncate(50.947563 * 100) / 100;
- Math.Truncate(5094.7563) / 100;
- 5094 / 100
- 50.94

А ось ваша відповідь усічена, тепер для форматування рядка просто виконайте наступне:

string s = string.Format("{0:N2}%", x); // No fear of rounding and takes the default number format

3
-1 Ви можете виконати формат, що залежить від культури, на тому ж string.Formatкроці, що і формат рядка. Дивіться мою відповідь нижче.
CesarGon

1
Це чудово. Я сподіваюся, що мій коментар зараз не виглядає таким дурним. :-) Тоді я поміняю свою голову.
CesarGon

1
Мені це вдалося, оскільки рішення щодо форматування рядків неймовірно просте, усічення було складніше.
Кайл Розендо

1
На жаль, ваше рішення не працює, коли число менше 1, щоб проілюструвати: 0,97, Чи є якесь вирішення для цієї ситуації?
Алі Дехган

2
@ Джоні, що не буде працювати, тому що він кругообіг - ОП хоче, щоб він усікався (а не був круглий). Різниця тонка.
BKSpurgeon

102

Наступне округлює числа, але показує лише до 2 знаків після коми (видаляючи будь-які проміжні нулі), завдяки .##.

decimal d0 = 24.154m;
decimal d1 = 24.155m;
decimal d2 = 24.1m;
decimal d3 = 24.0m;

d0.ToString("0.##");   //24.15
d1.ToString("0.##");   //24.16 (rounded up)
d2.ToString("0.##");   //24.1  
d3.ToString("0.##");   //24

http://dobrzanski.net/2009/05/14/c-decimaltostring-and-how-to-get-rid-of-trailing-zeros/


12
Це не працює. Спробуйте з 0,2415999. Це рішення кругляє, а не скорочує.
БЮР

5
Ух, стільки голосів набрали, і все-таки воно використовує округлення. Можливо, потрібно буде зазначити, що округлення спрямовується до найближчого запитуваного знаку після коми, тоді як обрізання відсікається після запиту найближчого десяткового знаку.
mysticcoder

1
@mysticcoder Я здогадуюсь, що моя відповідь отримує стільки результатів, тому що вони надходять на питання ops в пошуку Google так само, як і я, шукаючи видалення задніх нулів і не шукаючи бажання заокруглення питання про ops. Я думаю, я повинен видалити свою відповідь ...
Брайан Огден

@BrianOgden - Ні, не видаляйте. Я приїхав сюди, шукаючи вашої відповіді. +1
Роберто

35

Я пропоную вам срізати спочатку, а потім форматувати:

double a = 123.4567;
double aTruncated = Math.Truncate(a * 100) / 100;
CultureInfo ci = new CultureInfo("de-DE");
string s = string.Format(ci, "{0:0.00}%", aTruncated);

Використовуйте константу 100 для двозначного скорочення; використовуйте 1, за яким слідує стільки нулів, скільки цифр після десяткової крапки. Використовуйте назву культури, необхідну для налаштування результату форматування.


Я думаю, що замість цього new CultureInfo("de-DE")вам слід використовувати статичну властивістьCulture.InvariantCulture
vchan


13

я використовую price.ToString("0.00") для отримання провідних 0


6

Функція c #, висловлена ​​Кайлом Розендо:

string DecimalPlaceNoRounding(double d, int decimalPlaces = 2)
{
    d = d * Math.Pow(10, decimalPlaces);
    d = Math.Truncate(d);
    d = d / Math.Pow(10, decimalPlaces);
    return string.Format("{0:N" + Math.Abs(decimalPlaces) + "}", d);
}

5

Як щодо того, щоб додати один додатковий десятковий знак, який слід округлити, а потім відкинути:

var d = 0.241534545765;
var result1 = d.ToString("0.###%");

var result2 = result1.Remove(result1.Length - 1);

3
Смішно, як непрацююча відповідь має 60 голосів (станом на сьогодні), і це досить просте і безпроблемне рішення має лише один ....
Артур Казиханов

5
Це не спрацює в тому випадку, якщо округлення впливає на більш ніж одну цифру над відсічкою. Наприклад, з цим кодом 0,199999 буде 0,20, а не 0,19.
Бернем

4

Це працює для мене

string prouctPrice = Convert.ToDecimal(String.Format("{0:0.00}", Convert.ToDecimal(yourString))).ToString();

2

Я знаю, що це стара нитка, але я просто повинен був це зробити. Хоча інші підходи тут працюють, я хотів, щоб простий спосіб міг вплинути на багато дзвінків string.format. Тож додавання Math.Truncateвсіх дзвінків до насправді не було гарним варіантом. Крім того, що деякі форматування зберігаються в базі даних, це зробило це ще гірше.

Таким чином, я створив спеціальний постачальник форматів, який дозволив би мені додати усічення до рядка форматування, наприклад:

string.format(new FormatProvider(), "{0:T}", 1.1299); // 1.12
string.format(new FormatProvider(), "{0:T(3)", 1.12399); // 1.123
string.format(new FormatProvider(), "{0:T(1)0,000.0", 1000.9999); // 1,000.9

Реалізація досить проста і легко поширюється на інші вимоги.

public class FormatProvider : IFormatProvider, ICustomFormatter
{
    public object GetFormat(Type formatType)
    {
        if (formatType == typeof (ICustomFormatter))
        {
            return this;
        }
        return null;
    }

    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        if (arg == null || arg.GetType() != typeof (double))
        {
            try
            {
                return HandleOtherFormats(format, arg);
            }
            catch (FormatException e)
            {
                throw new FormatException(string.Format("The format of '{0}' is invalid.", format));
            }
        }

        if (format.StartsWith("T"))
        {
            int dp = 2;
            int idx = 1;
            if (format.Length > 1)
            {
                if (format[1] == '(')
                {
                    int closeIdx = format.IndexOf(')');
                    if (closeIdx > 0)
                    {
                        if (int.TryParse(format.Substring(2, closeIdx - 2), out dp))
                        {
                            idx = closeIdx + 1;
                        }
                    }
                    else
                    {
                        throw new FormatException(string.Format("The format of '{0}' is invalid.", format));
                    }
                }
            }
            double mult = Math.Pow(10, dp);
            arg = Math.Truncate((double)arg * mult) / mult;
            format = format.Substring(idx);
        }

        try
        {
            return HandleOtherFormats(format, arg);
        }
        catch (FormatException e)
        {
            throw new FormatException(string.Format("The format of '{0}' is invalid.", format));
        }
    }

    private string HandleOtherFormats(string format, object arg)
    {
        if (arg is IFormattable)
        {
            return ((IFormattable) arg).ToString(format, CultureInfo.CurrentCulture);
        }
        return arg != null ? arg.ToString() : String.Empty;
    }
}


1

До чого варто, для показу валюти можна використовувати "C":

double cost = 1.99;
m_CostText.text = cost.ToString("C"); /*C: format as currentcy */

Вихід: $1.99


0

Ви також можете написати свій власний IFormatProvider , хоча, мабуть, врешті-решт вам доведеться придумати спосіб зробити власне усічення.

.NET Framework також підтримує власне форматування. Зазвичай це передбачає створення класу форматування, який реалізує як IFormatProvider, так і ICustomFormatter . (msdn)

Принаймні, це було б легко повторним використанням.

Тут ви знайдете статтю про те, як реалізувати свій власний IFormatProvider / ICustomFormatter тут, у CodeProject . У цьому випадку найкраща ставка може бути "розширенням" існуючого цифрового формату. Це виглядає не надто важко.


0

Наступне може використовуватися лише для відображення, яке використовує властивість String ..

double value = 123.456789;
String.Format("{0:0.00}", value);

Це дасть "123,46". Питання конкретно не вимагає округлення.
Тобберот

0

Рішення:

var d = 0.123345678; 
var stringD = d.ToString(); 
int indexOfP = stringD.IndexOf("."); 
var result = stringD.Remove((indexOfP+1)+2);

(indexOfP + 1) +2 (це число залежить від того, скільки числа ви хочете зберегти. Я даю два, тому що власник питання хоче.)


0

Також зверніть увагу на інформацію про культуру вашої системи. Ось моє рішення без округлення.

У цьому прикладі ви просто повинні визначити змінну MyValue як подвійну. В результаті ви отримуєте відформатоване значення в рядковій змінній NewValue .

Примітка. Також встановіть C # за допомогою оператора:

using System.Globalization;  

string MyFormat = "0";
if (MyValue.ToString (CultureInfo.InvariantCulture).Contains (CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator))
   {
      MyFormat += ".00";
   }

string NewValue = MyValue.ToString(MyFormat);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.