Sử dụng Định dạng chuỗi để hiển thị số thập phân lên tới 2 vị trí hoặc số nguyên đơn giản


291

Tôi đã có một trường giá để hiển thị mà đôi khi có thể là 100 hoặc 100,99 hoặc 100,9, điều tôi muốn là hiển thị giá ở 2 vị trí thập phân chỉ khi số thập phân được nhập cho giá đó, ví dụ như là 100 nên chỉ nên hiển thị 100 không phải 100,00 và nếu giá là 100,2 thì nó sẽ hiển thị 100,20 tương tự cho 100,22 nên giống nhau. Tôi đã googled và bắt gặp một số ví dụ nhưng chúng không khớp chính xác những gì tôi muốn:

// just two decimal places
String.Format("{0:0.00}", 123.4567);      // "123.46"
String.Format("{0:0.00}", 123.4);         // "123.40"
String.Format("{0:0.00}", 123.0);         // "123.00"


1
RE: "Điều tôi muốn là chỉ hiển thị giá ở 2 vị trí thập phân nếu số thập phân được nhập cho giá đó" - vì vậy nếu người dùng nhập "100.00", bạn muốn hiển thị "100.00", nhưng nếu họ gõ "100" bạn chỉ muốn hiển thị "100"? - các loại số chỉ theo dõi giá trị của số - không phải là số nào trong số các chữ số không đáng kể được nhập bởi người dùng và không phải - vì bạn sẽ cần phải sử dụng một chuỗi.
BrainSlugs83

2
@BinaryWorrier Tôi nghĩ rằng câu hỏi này có thể là một bản sao, nhưng nó có câu trả lời tốt hơn và đầy đủ hơn. IMO cái khác nên được đánh dấu là bản sao của cái này.
Ryan Gates

chỉ cần thêm .Replace (". 00", "")
Dave Sumter

Câu trả lời:


156

Một cách không phù hợp sẽ là:

var my = DoFormat(123.0);

Với DoFormatmột cái gì đó như:

public static string DoFormat( double myNumber )
{
    var s = string.Format("{0:0.00}", myNumber);

    if ( s.EndsWith("00") )
    {
        return ((int)myNumber).ToString();
    }
    else
    {
        return s;
    }
}

Không thanh lịch nhưng làm việc cho tôi trong các tình huống tương tự trong một số dự án.


6
Đây thực sự không phải là câu hỏi đã được hỏi - nhưng đã có - tại sao không chỉ sử dụng chuỗi.Format ("{0: 0,00}"). Thay thế (". 00", "")?
BrainSlugs83

18
@ BrainSlugs83: tùy thuộc vào luồng hiện tại CurrentCulture, dấu phân cách thập phân có thể không có .. Trừ khi CultureInfo.InvariantCultuređược sử dụng với string.Format, bạn sẽ phải kiểm tra giá trị của CultureInfo.NumberFormat.NumberDecimalSeparator, và đó sẽ là một PITA thực sự. :)
Groo

@Uwe Keim Nếu tôi có 60000int và tôi muốn nó thì 60.000sao?
Prashant Pimpale

Câu trả lời này là một trường hợp "phát minh lại một bánh xe vuông". Không tính đến văn hóa hoặc thực tế là điều này đã được xử lý bởi .NET.
bytedev

523

Xin lỗi vì đã kích hoạt lại câu hỏi này, nhưng tôi không tìm thấy câu trả lời đúng ở đây.

Trong định dạng số, bạn có thể sử dụng 0làm nơi bắt buộc và #là nơi tùy chọn.

Vì thế:

// just two decimal places
String.Format("{0:0.##}", 123.4567);      // "123.46"
String.Format("{0:0.##}", 123.4);         // "123.4"
String.Format("{0:0.##}", 123.0);         // "123"

Bạn cũng có thể kết hợp 0với #.

String.Format("{0:0.0#}", 123.4567)       // "123.46"
String.Format("{0:0.0#}", 123.4)          // "123.4"
String.Format("{0:0.0#}", 123.0)          // "123.0"

Đối với phương pháp hình thành này luôn luôn được sử dụng CurrentCulture. Đối với một số nền văn hóa .sẽ được thay đổi thành ,.

Trả lời câu hỏi ban đầu:

Giải pháp đơn giản nhất đến từ @Andrew ( tại đây ). Vì vậy, cá nhân tôi sẽ sử dụng một cái gì đó như thế này:

var number = 123.46;
String.Format(number % 1 == 0 ? "{0:0}" : "{0:0.00}", number)

20
Lúc đầu, tôi nghĩ đây nên là câu trả lời, cho đến khi tôi đọc lại câu hỏi ban đầu nhiều lần. OP không hoàn toàn rõ ràng những gì anh ấy muốn chính xác, nhưng có vẻ như anh ấy luôn muốn 2 vị trí thập phân nếu ai đó nhập một phân số. Vì vậy, nếu ai đó đã nhập 1.1 thì anh ta muốn 1.10; mã này sẽ không làm điều đó.
Doug S

40
Rất tiếc, tôi đã đọc lại và bạn đã đúng. Vì vậy, đây không phải là câu trả lời đúng nhưng ít nhất ai đó có thể thấy điều này hữu ích.
Gh61

Những gì OP cần có thể đạt được với điều này: stackoverflow.com/a/33180829/2321042
Andrew

Tôi chỉ thấy nó hữu ích và (phần nào) khớp với những gì BoundField trong GridView thực hiện với SqlDouble và không có hướng dẫn định dạng. Bạn phải chỉ ra tối đa # bạn sẽ hiển thị. (Vs. BoundField, vui mừng hiển thị bao nhiêu hoặc ít tùy thích)
fortboise

Yup điều này rất hữu ích, nhưng làm thế nào để chỉ hiển thị hai số thập phân nếu có số thập phân? tức là nếu nó là một số nguyên thì không hiển thị số thập phân?
Nigel Fds

64

Đây là một trường hợp sử dụng định dạng số nổi phổ biến.

Thật không may, tất cả các chuỗi định dạng một chữ cái tích hợp (ví dụ: F, G, N) sẽ không đạt được điều này trực tiếp.
Ví dụ: num.ToString("F2")sẽ luôn hiển thị 2 vị trí thập phân như123.40 .

Bạn sẽ phải sử dụng 0.##mô hình ngay cả khi nó trông hơi dài dòng.

Một ví dụ mã hoàn chỉnh:

double a = 123.4567;
double b = 123.40;
double c = 123.00;

string sa = a.ToString("0.##"); // 123.46
string sb = b.ToString("0.##"); // 123.4
string sc = c.ToString("0.##"); // 123

7
Nhưng anh ta muốn 123,40 chứ không phải 123,4.
Andrew

8
Không giải quyết câu hỏi này nhưng giải quyết của tôi. Tôi ủng hộ điều này để đưa ra cho mọi người khác xem.
Emad

46

Câu hỏi cũ nhưng tôi muốn thêm tùy chọn đơn giản nhất theo ý kiến ​​của tôi.

Không có hàng ngàn dấu phân cách:

value.ToString(value % 1 == 0 ? "F0" : "F2")

Với hàng ngàn dải phân cách:

value.ToString(value % 1 == 0 ? "N0" : "N2")

Tương tự nhưng với String.Format :

String.Format(value % 1 == 0 ? "{0:F0}" : "{0:F2}", value) // Without thousands separators
String.Format(value % 1 == 0 ? "{0:N0}" : "{0:N2}", value) // With thousands separators

Nếu bạn cần nó ở nhiều nơi , tôi sẽ sử dụng logic này trong một phương thức mở rộng :

public static string ToCoolString(this decimal value)
{
    return value.ToString(value % 1 == 0 ? "N0" : "N2"); // Or F0/F2 ;)
}

28

thử

double myPrice = 123.0;

String.Format(((Math.Round(myPrice) == myPrice) ? "{0:0}" : "{0:0.00}"), myPrice);

5
chuỗi.Format ((số% 1) == 0? "{0: 0}": "{0: 0.00}", số);
Patrick

8

Tôi không biết cách nào để đặt một điều kiện trong trình xác định định dạng, nhưng bạn có thể viết trình định dạng của riêng bạn:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
               // all of these don't work
            Console.WriteLine("{0:C}", 10);
            Console.WriteLine("{0:00.0}", 10);
            Console.WriteLine("{0:0}", 10);
            Console.WriteLine("{0:0.00}", 10);
            Console.WriteLine("{0:0}", 10.0);
            Console.WriteLine("{0:0}", 10.1);
            Console.WriteLine("{0:0.00}", 10.1);

          // works
            Console.WriteLine(String.Format(new MyFormatter(),"{0:custom}", 9));
            Console.WriteLine(String.Format(new MyFormatter(),"{0:custom}", 9.1));
            Console.ReadKey();
        }
    }

    class MyFormatter : IFormatProvider, ICustomFormatter
    {
        public string Format(string format, object arg, IFormatProvider formatProvider)
        {
            switch (format.ToUpper())
            {
                case "CUSTOM":
                    if (arg is short || arg is int || arg is long)
                        return arg.ToString();
                    if (arg is Single || arg is Double)
                        return String.Format("{0:0.00}",arg);
                    break;
                // Handle other
                default:
                    try
                    {
                        return HandleOtherFormats(format, arg);
                    }
                    catch (FormatException e)
                    {
                        throw new FormatException(String.Format("The format of '{0}' is invalid.", format), e);
                    }
            }
            return arg.ToString(); // only as a last resort
        }

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

        public object GetFormat(Type formatType)
        {
            if (formatType == typeof(ICustomFormatter))
                return this;
            return null;
        }
    }
}

6

Đây là một thay thế cho phương pháp của Uwe Keim, vẫn sẽ duy trì cuộc gọi phương thức tương tự:

var example1 = MyCustomFormat(123.1);  // Output: 123.10
var example2 = MyCustomFormat(123.95); // Output: 123.95
var example3 = MyCustomFormat(123);    // Output: 123

Với MyCustomFormatmột cái gì đó như:

public static string MyCustomFormat( double myNumber )
{
    var str (string.Format("{0:0.00}", myNumber))
    return (str.EndsWith(".00") ? str.Substring(0, strLastIndexOf(".00")) : str;
}

Điều này không phù hợp với tôi vì có vẻ như TrimEnd lấy một loạt các ký tự như {',', '.', ''} Thay vì một chuỗi như ".00" - Xem msdn.microsoft.com/en-us/ thư viện /
system.opes.trimend.aspx

Bạn nói đúng - không chắc là tôi đã bỏ lỡ điều đó như thế nào. Tôi đã cập nhật để hoạt động chính xác.
Steve

5
Tùy thuộc vào luồng hiện tại CurrentCulture, dấu tách thập phân có thể không .. Trừ khi CultureInfo.InvariantCultuređược sử dụng với string.Format, bạn sẽ phải kiểm tra giá trị của CultureInfo.NumberFormat.NumberDecimalSeparator, điều này khá không phù hợp.
Groo

6

Mã một dòng đơn giản:

public static string DoFormat(double myNumber)
{
    return string.Format("{0:0.00}", myNumber).Replace(".00","");
}

Vấn đề với điều này là nếu nó được chạy trong đó dấu tách thập phân là dấu phẩy. Kiểm tra các ý kiến ​​cho câu trả lời này .
Andrew

6

Nếu chương trình của bạn cần chạy nhanh, hãy gọi value.ToString (formatString) để có hiệu suất định dạng chuỗi nhanh hơn ~ 35% so với $ "{value: formatString}" và string.Format (formatString, value).

Dữ liệu

Hiệu suất định dạng chuỗi C # - VS2017 15.4.5

using System;
using System.Diagnostics;

public static class StringFormattingPerformance
{
   public static void Main()
   {
      Console.WriteLine("C# String Formatting Performance");
      Console.WriteLine("Milliseconds Per 1 Million Iterations - Best Of 5");
      long stringInterpolationBestOf5 = Measure1MillionIterationsBestOf5(
          (double randomDouble) =>
          {
             return $"{randomDouble:0.##}";
          });
      long stringDotFormatBestOf5 = Measure1MillionIterationsBestOf5(
          (double randomDouble) =>
          {
             return string.Format("{0:0.##}", randomDouble);
          });
      long valueDotToStringBestOf5 = Measure1MillionIterationsBestOf5(
          (double randomDouble) =>
          {
             return randomDouble.ToString("0.##");
          });
      Console.WriteLine(
$@"            $""{{value:formatString}}"": {stringInterpolationBestOf5} ms
 string.Format(formatString, value): {stringDotFormatBestOf5} ms
       value.ToString(formatString): {valueDotToStringBestOf5} ms");
   }

   private static long Measure1MillionIterationsBestOf5(
       Func<double, string> formatDoubleUpToTwoDecimalPlaces)
   {
      long elapsedMillisecondsBestOf5 = long.MaxValue;
      for (int perfRunIndex = 0; perfRunIndex < 5; ++perfRunIndex)
      {
         var random = new Random();
         var stopwatch = Stopwatch.StartNew();
         for (int i = 0; i < 1000000; ++i)
         {
            double randomDouble = random.NextDouble();
            formatDoubleUpToTwoDecimalPlaces(randomDouble);
         }
         stopwatch.Stop();
         elapsedMillisecondsBestOf5 = Math.Min(
            elapsedMillisecondsBestOf5, stopwatch.ElapsedMilliseconds);
      }
      return elapsedMillisecondsBestOf5;
   }
}

Mã đầu ra

C# String Formatting Performance
Milliseconds Per 1 Million Iterations - Best Of 5
            $"{value:formatString}": 419 ms
 string.Format(formatString, value): 419 ms
       value.ToString(formatString): 264 ms

Người giới thiệu

Chuỗi định dạng số tùy chỉnh [docs.microsoft.com]

Ví dụ về biểu đồ Bart của Qt [doc.qt.io]


5

Tôi sợ rằng không có định dạng tích hợp sẽ làm điều này. Bạn sẽ phải sử dụng một định dạng khác nhau tùy thuộc vào việc giá trị có phải là một số nguyên hay không. Hoặc luôn định dạng đến 2 vị trí thập phân và thao tác chuỗi sau đó để xóa bất kỳ dấu ".00" nào.


4

Nếu không có câu trả lời nào khác phù hợp với bạn, có thể là do bạn đang ràng buộc ContentPropertyđiều khiển trong OnLoadchức năng, điều đó có nghĩa là điều này sẽ không hoạt động:

private void UserControl_Load(object sender, RoutedEventArgs e)
{
  Bind.SetBindingElement(labelName, String.Format("{0:0.00}", PropertyName), Label.ContentProperty) 
}

Giải pháp rất đơn giản: có một ContentStringFormatthuộc tính trong xaml. Vì vậy, khi bạn tạo nhãn làm điều này:

//if you want the decimal places definite
<Label Content="0" Name="labelName" ContentStringFormat="0.00"/>

Hoặc là

//if you want the decimal places to be optional
<Label Content="0" Name="labelName" ContentStringFormat="0.##"/>

3

một cái gì đó như thế này cũng sẽ hoạt động:

String.Format("{0:P}", decimal.Parse(Resellers.Fee)).Replace(".00", "")

Điều đó cho một phần trăm?


2

Để làm cho mã rõ ràng hơn mà Kahia đã viết (rõ ràng nhưng khó khăn khi bạn muốn thêm văn bản vào đó) ... hãy thử giải pháp đơn giản này.

if (Math.Round((decimal)user.CurrentPoints) == user.CurrentPoints)
     ViewBag.MyCurrentPoints = String.Format("Your current Points: {0:0}",user.CurrentPoints);
else
     ViewBag.MyCurrentPoints = String.Format("Your current Points: {0:0.0}",user.CurrentPoints);

Tôi đã phải thêm các diễn viên phụ (thập phân) để có Math.Round so sánh hai biến thập phân.


1

Điều này làm việc cho tôi!

String amount= "123.0000";
String.Format("{0:0.##}", amount);      // "123.00"

1
Điều đó không hiệu quả. Anh ta muốn 123.00 được hiển thị là "123" và 123,50 là "123,50".
Andrew

1

Khi xử lý số thập phân đến từ cơ sở dữ liệu SQL (T-), bạn muốn có thể chuyển đổi số thập phân nullable và không nullable với x vị trí thập phân và có thể xem lại mã dễ dàng theo định nghĩa bảng của bạn - và tất nhiên, hiển thị đúng số thập phân cho người dùng.

Thật không may, Entity Framework không tự động chuyển đổi một cái gì đó như SQL decimal(18,2) thành .NET tương đương với cùng số vị trí thập phân (vì chỉ có số thập phân với độ chính xác đầy đủ có sẵn). Bạn phải cắt các vị trí thập phân bằng tay.

Vì vậy, tôi đã làm theo cách này:

public static class Extensions
{
    public static string ToStringDecimal(this decimal d, byte decimals)
    {
        var fmt = (decimals>0) ? "0." + new string('0', decimals) : "0";
        return d.ToString(fmt);
    }

    public static string ToStringDecimal(this decimal? d, byte decimals)
    {
        if (!d.HasValue) return "";
        return ToStringDecimal(d.Value, decimals);
    }
}

Cách sử dụng ví dụ:

void Main()
{
    decimal d = (decimal)1.2345;
    decimal? d2 = null; 

    Console.WriteLine(d.ToStringDecinal(2)); // prints: "1.23" (2 decimal places)
    Console.WriteLine(d.ToStringDecinal(0)); // prints: "1" (show integer number)
    Console.WriteLine(d2.ToStringDecimal(2)); // prints: "" (show null as empty string)
}
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.