Định dạng C # Double - ToString () với hai chữ số thập phân nhưng không làm tròn số


153

Làm cách nào để định dạng a Doublethành a Stringtrong C # để chỉ có hai chữ số thập phân?

Nếu tôi sử dụng String.Format("{0:0.00}%", myDoubleValue)số được làm tròn và tôi muốn cắt ngắn đơn giản mà không cần làm tròn. Tôi cũng muốn việc chuyển đổi Stringtrở nên nhạy cảm về văn hóa.


Bạn có ý nghĩa gì bởi "văn hóa nhạy cảm"? Điều đó có nghĩa là kết quả của định dạng phải thay đổi tùy thuộc vào giá trị văn hóa do lập trình viên cung cấp? Hay bạn muốn sử dụng bất cứ văn hóa nào là mặc định cho luồng hiện tại?
CesarGon

Câu trả lời:


204

Tôi sử dụng như sau:

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

Ví dụ:

Nếu số là 50.947563 và bạn sử dụng như sau, điều sau đây sẽ xảy ra:

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

Và có câu trả lời của bạn bị cắt ngắn, bây giờ để định dạng chuỗi chỉ cần làm như sau:

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

3
-1 Bạn có thể thực hiện định dạng nhạy cảm văn hóa trong cùng một string.Formatbước định dạng chuỗi. Xem câu trả lời của tôi dưới đây.
CesarGon

1
Thật tuyệt. Tôi hy vọng bình luận của tôi không có vẻ ngớ ngẩn bây giờ. :-) Tôi sẽ thay đổi downvote của tôi sau đó.
CesarGon

1
Đối với tôi nó đã làm, vì giải pháp về định dạng chuỗi là cực kỳ đơn giản, việc cắt ngắn khó khăn hơn.
Kyle Rosendo

1
Thật không may, giải pháp của bạn không giải quyết được khi số nhỏ hơn 1, để minh họa: 0.97, Có cách giải quyết nào cho tình huống này không?
Ali Deh Afghanistan

2
@Jonny sẽ không hoạt động vì nó làm tròn - OP muốn nó cắt ngắn (và không làm tròn). Sự khác biệt là tinh tế.
BKSpurgeon

102

Sau đây làm tròn các số, nhưng chỉ hiển thị tối đa 2 vị trí thập phân (loại bỏ bất kỳ số 0 nào), nhờ .##.

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
Điều này không hoạt động. Hãy thử với 0,2415999. Giải pháp này làm tròn, không cắt ngắn.
BJury

5
Ồ, rất nhiều phiếu bầu và nó đang sử dụng làm tròn số. Có thể cần phải chỉ ra rằng làm tròn đang hướng tới vị trí thập phân gần nhất được yêu cầu, trong khi cắt ngắn đang cắt sau vị trí thập phân gần nhất được yêu cầu.
huyền bí

1
@mysticcoder Tôi đoán câu trả lời của tôi nhận được rất nhiều sự ủng hộ vì họ tìm đến câu hỏi của ops trong một tìm kiếm của Google giống như tôi đã làm, tìm cách loại bỏ các số 0 ở cuối và không tìm kiếm mong muốn làm tròn của câu hỏi ops. Tôi đoán tôi nên xóa câu trả lời của mình ...
Brian Ogden

@BrianOgden - Không, vui lòng không xóa. Tôi đến đây để tìm câu trả lời của bạn. +1
Roberto

35

Tôi đề nghị bạn cắt ngắn trước, sau đó định dạng:

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

Sử dụng hằng số 100 cho 2 chữ số cắt ngắn; sử dụng 1 theo sau là nhiều số không dưới dạng chữ số sau dấu thập phân bạn muốn. Sử dụng tên văn hóa bạn cần để điều chỉnh kết quả định dạng.


Tôi nghĩ rằng thay vì new CultureInfo("de-DE"), bạn nên sử dụng thuộc tính tĩnhCulture.InvariantCulture
vchan


13

tôi sử dụng price.ToString("0.00") để có được số 0 hàng đầu


6

Hàm c #, như được thể hiện bởi Kyle Rozendo:

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

Làm thế nào về việc thêm một số thập phân được làm tròn và sau đó loại bỏ:

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

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

3
Thật buồn cười khi một câu trả lời không hoạt động có 60 phiếu bầu (tính đến ngày hôm nay) và giải pháp chống đạn khá đơn giản này chỉ có một ....
Arthur Kazykhanov

5
Điều này sẽ không hoạt động trong trường hợp làm tròn ảnh hưởng đến nhiều hơn một chữ số trên ngưỡng. Ví dụ: 0.199999 sẽ kết thúc là 0,20 với mã này, thay vì 0,19.
Bernem

4

Cái này làm việc cho tôi

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

2

Tôi biết đây là một chủ đề cũ nhưng tôi đã phải làm điều này. Trong khi các phương pháp khác ở đây hoạt động, tôi muốn một cách dễ dàng để có thể ảnh hưởng đến rất nhiều cuộc gọi đến string.format. Vì vậy, thêm Math.Truncatetất cả các cuộc gọi vào thực sự không phải là một lựa chọn tốt. Ngoài ra, một số định dạng được lưu trữ trong cơ sở dữ liệu, nó còn làm cho nó tồi tệ hơn.

Vì vậy, tôi đã tạo một nhà cung cấp định dạng tùy chỉnh cho phép tôi thêm cắt ngắn vào chuỗi định dạng, ví dụ:

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

Việc thực hiện khá đơn giản và dễ dàng mở rộng cho các yêu cầu khác.

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

2

Tôi gặp vấn đề với Xamarin Forms và đã giải quyết nó bằng cách này:

percent.ToString("0.##"+"%")

1

Để những gì có giá trị, để hiển thị tiền tệ, bạn có thể sử dụng "C":

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

Đầu ra: $1.99


0

Bạn cũng có thể viết IFormatProvider của riêng mình , mặc dù tôi cho rằng cuối cùng bạn sẽ phải nghĩ ra cách để thực hiện cắt ngắn thực tế.

.NET Framework cũng hỗ trợ định dạng tùy chỉnh. Điều này thường liên quan đến việc tạo ra một lớp định dạng thực hiện cả IFormatProvider và ICustomFormatter . (msd)

Ít nhất nó sẽ dễ dàng tái sử dụng.

Có một bài viết về cách triển khai IFormatProvider / ICustomFormatter của riêng bạn tại đây tại CodeProject . Trong trường hợp này, "mở rộng" một định dạng số hiện có có thể là đặt cược tốt nhất. Nó không quá khó.


0

Dưới đây chỉ có thể được sử dụng để hiển thị sử dụng thuộc tính của Chuỗi ..

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

Điều này sẽ cho "123,46". Câu hỏi đặc biệt yêu cầu không làm tròn số.
Tobberoth

0

Giải pháp:

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

(indexOfP + 1) +2 (con số này phụ thuộc vào số lượng bạn muốn giữ lại. Tôi cung cấp cho nó hai vì chủ sở hữu câu hỏi muốn.)


0

Cũng lưu ý các CultureInformation của hệ thống. Đây là giải pháp của tôi mà không làm tròn.

Trong ví dụ này, bạn chỉ cần xác định biến MyValue là gấp đôi. Kết quả là bạn nhận được giá trị định dạng của mình trong biến chuỗi NewValue .

Lưu ý - Cũng đặt câu lệnh sử dụng C #:

using System.Globalization;  

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

string NewValue = MyValue.ToString(MyFormat);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.