Xóa các số 0 ở cuối


177

Tôi có một số trường được trả về bởi một bộ sưu tập như

2.4200
2.0044
2.0000

Tôi muốn kết quả như

2.42
2.0044
2

Tôi đã thử với String.Format, nhưng nó trả về 2.0000và thiết lập nó để làm N0tròn các giá trị khác.


3
loại bản ghi ban đầu là chuỗi ??
Singleton

2
Xem câu trả lời của tôi: String.Format()với 'G' sẽ nhận được những gì bạn muốn .. tôi đã cập nhật câu trả lời của mình bằng một liên kết đến các định dạng số tiêu chuẩn. Rất tiện dụng.
Tai chó

3
Một số thập phân có thể được chuyển thành doublevà mặc định ToStringcho double phát ra các số 0 ở cuối. đọc cái này
Shimmy Weitzhandler

2
Và nó có thể sẽ tốn ít hiệu năng hơn (xen kẽ số lượng bản ghi rất lớn) so với việc chuyển "G" dưới dạng định dạng chuỗi cho ToStringhàm.
Shimmy Weitzhandler

4
Bạn không nên chuyển đổi một số thập phân thành gấp đôi, nó sẽ mất đi ý nghĩa và có thể giới thiệu sức mạnh của hai điểm không chính xác làm tròn.
kristianp

Câu trả lời:


167

Nó không đơn giản như thế này, nếu đầu vào là một chuỗi? Bạn có thể sử dụng một trong những điều sau đây:

string.Format("{0:G29}", decimal.Parse("2.0044"))

decimal.Parse("2.0044").ToString("G29")

2.0m.ToString("G29")

Điều này sẽ làm việc cho tất cả các đầu vào.

Cập nhật Kiểm tra các định dạng số chuẩn mà tôi phải đặt rõ ràng bộ xác định chính xác thành 29 vì các tài liệu nêu rõ:

Tuy nhiên, nếu số là số thập phân và bộ xác định chính xác bị bỏ qua, ký hiệu điểm cố định luôn được sử dụng và các số 0 ở cuối được giữ nguyên

Cập nhật Konrad chỉ ra trong các ý kiến:

Coi chừng các giá trị như 0,000001. Định dạng G29 sẽ trình bày chúng theo cách ngắn nhất có thể để nó sẽ chuyển sang ký hiệu số mũ. string.Format("{0:G29}", decimal.Parse("0.00000001",System.Globalization.CultureInfo.GetCultureInfo("en-US")))sẽ cho kết quả "1E-08".


1
Trong tất cả các câu trả lời, bạn có ít bước nhất liên quan. Cảm ơn Tai chó.
Zo có

4
var d = 2,0m; d.ToString ("G");
Dave Hillier

3
@Dave Hillier - Tôi hiểu rồi, tôi đã sửa câu trả lời của mình. Chúc mừng. [thêm rõ ràng 'bộ xác định chính xác']
Tai chó

16
Coi chừng các giá trị như 0,000001. Định dạng G29 sẽ trình bày chúng theo cách ngắn nhất có thể để nó sẽ chuyển sang ký hiệu số mũ. chuỗi.Format ("{0: G29}", binary.Pude ("0,00000001", System.Globalization.CARMInfo.GetCARMInfo ("en-US"))) sẽ cho kết quả "1E-08"
Konrad

15
@Konrad - có cách nào để tránh ký hiệu Khoa học cho các số có 5 hoặc 6 chữ số thập phân không?
Jill

202

Tôi gặp vấn đề tương tự nhưng trong trường hợp tôi không kiểm soát được đầu ra thành chuỗi, được một thư viện chăm sóc. Sau khi xem xét chi tiết trong việc triển khai loại Thập phân (xem http://msdn.microsoft.com/en-us/l Library / system.decimal.getbits.aspx ), tôi đã nghĩ ra một mẹo gọn gàng (ở đây là một tiện ích mở rộng phương pháp):

public static decimal Normalize(this decimal value)
{
    return value/1.000000000000000000000000000000000m;
}

Phần số mũ của số thập phân được giảm xuống chỉ còn những gì cần thiết. Gọi ToString () trên số thập phân đầu ra sẽ ghi số mà không có dấu nào 0. Ví dụ

1.200m.Normalize().ToString();

29
Câu trả lời này sở hữu bởi vì không giống như mọi câu trả lời khác về câu hỏi này (và thậm chí toàn bộ chủ đề) thực sự là CÔNG TRÌNH và thực hiện những gì OP đang hỏi.
Coxy

2
số 0 là một số lượng chính xác ở đây hay chỉ để bao gồm hầu hết các giá trị dự kiến?
Simon_Weaver

3
MSDN nói "Hệ số tỷ lệ hoàn toàn là số 10, được tăng lên theo cấp số nhân từ 0 đến 28", mà tôi hiểu là số thập phân sẽ có nhiều nhất là 28 chữ số qua dấu thập phân. Bất kỳ số 0> 28 nào cũng hoạt động.
Thomas Materna

2
Đây là câu trả lời tốt nhất! Số trong câu trả lời có 34 hình, 1tiếp theo là 33- 0giây, nhưng số đó tạo ra chính xác giống decimalnhư một số có 29 hình, một 1và 28- 0giây. Giống như @ThomasMaterna đã nói trong bình luận của mình. Không System.Decimalcó thể có nhiều hơn 29 hình (các số có chữ số hàng đầu lớn hơn chỉ 79228...có thể có tổng số 28 hình). Nếu bạn muốn có nhiều số 0 khác, hãy nhân lên 1.000...mthay vì chia. Ngoài ra, Math.Roundcó thể cắt bỏ một số số không, ví dụ như Math.Round(27.40000m, 2)cho 27.40m, vì vậy chỉ còn lại một số không.
Jeppe Stig Nielsen

2
Thủ thuật tuyệt vời nhưng KHÔNG hoạt động trên Mono và không được bảo đảm hoạt động trên các phiên bản tính năng của .NET
Bigjim 17/12/13

87

Theo tôi, an toàn hơn khi sử dụng Chuỗi định dạng số tùy chỉnh .

decimal d = 0.00000000000010000000000m;
string custom = d.ToString("0.#########################");
// gives: 0,0000000000001
string general = d.ToString("G29");
// gives: 1E-13

25
+1 cho câu trả lời duy nhất dựa trên hành vi ổn định, được ghi lại.
sinelaw

3
Bạn nên đặt ký tự 28 '#', xem blackwasp.co.uk/DecimalTrailingZeroes.aspx .
Jaime Hablutzel

32

Tôi sử dụng mã này để tránh ký hiệu khoa học "G29":

public static string DecimalToString(this decimal dec)
{
    string strdec = dec.ToString(CultureInfo.InvariantCulture);
    return strdec.Contains(".") ? strdec.TrimEnd('0').TrimEnd('.') : strdec;
}

EDIT: sử dụng hệ thống CultureInfo.NumberFormat.NumberDecimalSpayator:

public static string DecimalToString(this decimal dec)
{
    string sep = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
    string strdec = dec.ToString(CultureInfo.CurrentCulture);
    return strdec.Contains(sep) ? strdec.TrimEnd('0').TrimEnd(sep.ToCharArray()) : strdec;
}

1
Đây là một câu trả lời tuyệt vời. Điều đó rất đơn giản và bạn có thể thấy chính xác những gì đang xảy ra thay vì sử dụng bộ định dạng chuỗi ma thuật.
Timothy Gonzalez

9
Đẹp, nhưng nó sẽ không hoạt động đối với các nền văn hóa sử dụng dấu phẩy cho dấu phân cách thập phân. Bạn cần sử dụngCulture.NumberFormat.NumberDecimalSeparator
blearyeye

1
Cách tiếp cận tốt nhất. Mọi thứ khác là phức tạp không cần thiết. Chỉ cần nhớ luôn luôn để kiểm tra nếu số của bạn có chứa dấu thập phân.
RRM

1
Để là một tiện ích mở rộng bị thiếu "cái này" trước tham số: chuỗi tĩnh công khai DecimalToString (số thập phân này)
João Antunes

Cảm ơn bạn rất nhiều cho các ý kiến. Tôi đã cập nhật câu trả lời với một phiên bản mới với các mẹo.
x7BiT

19

Sử dụng #biểu tượng băm ( ) để chỉ hiển thị dấu 0 khi cần thiết. Xem các bài kiểm tra dưới đây.

decimal num1 = 13.1534545765;
decimal num2 = 49.100145;
decimal num3 = 30.000235;

num1.ToString("0.##");       //13.15%
num2.ToString("0.##");       //49.1%
num3.ToString("0.##");       //30%

7
Không phải là một câu trả lời. Bạn không loại bỏ các số 0 ở cuối, bạn đang loại bỏ độ chính xác. Phương pháp được đề xuất của bạn num1.ToString("0.##")sẽ trả về 13.1534545765(không thay đổi) vì không có bất kỳ số 0 nào.
Jan 'splite' K.

Và đó chính xác là lý do tại sao tôi hiển thị câu trả lời cho ba đầu vào được đề xuất của mình để người dùng có thể thấy giải pháp của tôi hoạt động như thế nào.
Fizzix

Nó không trả lời câu hỏi ngay cả khi bạn liệt kê các đầu vào được đề xuất.
Dave Friedel

2
Id upvote này 10 lần nếu tôi có thể. Chính xác những gì tôi cần!
SubqueryCrunch

1
Câu trả lời hoàn hảo cho câu hỏi. Câu trả lời TỐT NHẤT theo ý kiến ​​của tôi. Nhận xét rằng nó loại bỏ độ chính xác là chính xác, nhưng đó không phải là quesiton. Quan trọng nhất - đó là những gì tôi cần. Người dùng của tôi thường sẽ nhập toàn bộ số, có thể là 2,5, nhưng tôi cần hỗ trợ 3 chữ số ngoài dấu thập phân. Vì vậy, tôi muốn đưa cho họ những gì họ đã nhập, không phải với một loạt số không họ đã nhập. ví dụ: Console.Write ($ "num3 = {num3: 0. ##}"); => num3 = 30
bobwki


2

Một cách tiếp cận ở mức độ rất thấp, nhưng tôi tin rằng đây sẽ là cách hiệu quả nhất bằng cách chỉ sử dụng các phép tính số nguyên nhanh (và không có phương pháp phân tích chuỗi và phân tích chuỗi chậm):

public static decimal Normalize(this decimal d)
{
    int[] bits = decimal.GetBits(d);

    int sign = bits[3] & (1 << 31);
    int exp = (bits[3] >> 16) & 0x1f;

    uint a = (uint)bits[2]; // Top bits
    uint b = (uint)bits[1]; // Middle bits
    uint c = (uint)bits[0]; // Bottom bits

    while (exp > 0 && ((a % 5) * 6 + (b % 5) * 6 + c) % 10 == 0)
    {
        uint r;
        a = DivideBy10((uint)0, a, out r);
        b = DivideBy10(r, b, out r);
        c = DivideBy10(r, c, out r);
        exp--;
    }

    bits[0] = (int)c;
    bits[1] = (int)b;
    bits[2] = (int)a;
    bits[3] = (exp << 16) | sign;
    return new decimal(bits);
}

private static uint DivideBy10(uint highBits, uint lowBits, out uint remainder)
{
    ulong total = highBits;
    total <<= 32;
    total = total | (ulong)lowBits;

    remainder = (uint)(total % 10L);
    return (uint)(total / 10L);
}

1
Tôi đã cố gắng đi theo con đường này, nhưng đã tối ưu hóa nó hơn nữa để nó thực sự nhanh hơn nhiều so với của bạn, bằng cách không phân chia himid int (của bạn ab) trong mỗi lần lặp nếu tất cả đều bằng không. Tuy nhiên sau đó tôi đã tìm thấy giải pháp đơn giản đáng ngạc nhiên này cũng dễ dàng đánh bại những gì bạn và tôi đã đưa ra với hiệu suất khôn ngoan .
Eugene Beresovsky

2

Điều này sẽ làm việc:

decimal source = 2.4200m;
string output = ((double)source).ToString();

Hoặc nếu giá trị ban đầu của bạn là string:

string source = "2.4200";
string output = double.Parse(source).ToString();

Hãy chú ý đến nhận xét này .


2
@Damien, vâng, và lưu ý rằng, đối với những lần thanh lọc này (bạn sẽ không cảm thấy gì trừ khi bạn thực hiện hàng tỷ bản ghi), thứ nhất vì gấp đôi nhanh hơn, thứ hai, bởi vì việc chuyển định dạng chuỗi sang hàm ToString có hiệu suất cao hơn không thông qua thông số. một lần nữa, bạn sẽ không cảm thấy bất cứ điều gì trừ khi bạn làm việc với ánh mắt của hồ sơ.
Shimmy Weitzhandler

1
Bạn không phải chỉ định G, vì double.ToStringmặc định loại bỏ các số 0 ở cuối.
Shimmy Weitzhandler

4
Coi chừng các giá trị như 0,000001. Chúng sẽ được trình bày trong ký hiệu số mũ. double.Pude ("0,00000001", System.Globalization.CARMInfo.GetCARMInfo ("en-US")). ToString () sẽ cho kết quả là "1E-08"
Konrad

17
Đừng bao giờ làm điều này. Thông thường, lý do bạn có số thập phân là vì bạn đại diện cho một số chính xác (không xấp xỉ như một số kép). Cấp, lỗi dấu phẩy động này có thể khá nhỏ, nhưng có thể dẫn đến việc hiển thị số không chính xác, không hơn không kém
Adam Tegen

2
Ouch, chuyển đổi một kiểu dữ liệu 128 bit (thập phân) thành kiểu dữ liệu 64 bit (gấp đôi) để định dạng, không phải là một ý tưởng hay!
avl_sweden

2

Cái này đơn giản.

decimal decNumber = Convert.ToDecimal(value);
        return decNumber.ToString("0.####");

Thử nghiệm.

Chúc mừng :)


1

Phụ thuộc vào những gì số của bạn đại diện và cách bạn muốn quản lý các giá trị: đó có phải là tiền tệ không, bạn có cần làm tròn hoặc cắt bớt không, bạn có cần làm tròn số này chỉ để hiển thị không?

Nếu để hiển thị, hãy xem xét định dạng các số là x.ToString ("")

http://msdn.microsoft.com/en-us/l Library / dawawy9k.aspx

http://msdn.microsoft.com/en-us/l Library / 0c899ak8.aspx

Nếu nó chỉ làm tròn, hãy sử dụng quá tải Math.Round yêu cầu quá tải MidPointRounding

http://msdn.microsoft.com/en-us/l Library / ms131274.aspx )

Nếu bạn nhận được giá trị của mình từ cơ sở dữ liệu, hãy xem xét việc truyền thay vì chuyển đổi: double value = (thập phân) myRecord ["cộtName"];


0

Bạn chỉ có thể đặt là:

decimal decNumber = 23.45600000m;
Console.WriteLine(decNumber.ToString("0.##"));

1
Để làm việc đó, bạn nên đặt hai mươi tám ký tự thay vì chỉ hai.
Jaime Hablutzel

vâng, tôi đã hiểu nhầm câu hỏi của anh ấy ... = /
Danilo Ferreira

0

Trong trường hợp bạn muốn giữ số thập phân, hãy thử ví dụ sau:

number = Math.Floor(number * 100000000) / 100000000;

0

Đang cố gắng thực hiện giải pháp thân thiện hơn với DecimalToString ( https://stackoverflow.com/a 432486763/3852139 ):

private static decimal Trim(this decimal value)
{
    var s = value.ToString(CultureInfo.InvariantCulture);
    return s.Contains(CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator)
        ? Decimal.Parse(s.TrimEnd('0'), CultureInfo.InvariantCulture)
        : value;
}

private static decimal? Trim(this decimal? value)
{
    return value.HasValue ? (decimal?) value.Value.Trim() : null;
}

private static void Main(string[] args)
{
    Console.WriteLine("=>{0}", 1.0000m.Trim());
    Console.WriteLine("=>{0}", 1.000000023000m.Trim());
    Console.WriteLine("=>{0}", ((decimal?) 1.000000023000m).Trim());
    Console.WriteLine("=>{0}", ((decimal?) null).Trim());
}

Đầu ra:

=>1
=>1.000000023
=>1.000000023
=>

-1

Câu trả lời rất đơn giản là sử dụng TrimEnd (). Đây là kết quả,

double value = 1.00;
string output = value.ToString().TrimEnd('0');

Đầu ra là 1 Nếu giá trị của tôi là 1,01 thì đầu ra của tôi sẽ là 1,01


4
Nếu như value = 100thế nào?
Stephen Drew

4
@Raj De Inno Ngay cả khi giá trị là 1,00 thì sản lượng mà nó đưa ra là "1." không phải "1"
Simba

-1

Đoạn mã sau có thể được sử dụng để không sử dụng kiểu chuỗi:

int decimalResult = 789.500
while (decimalResult>0 && decimalResult % 10 == 0)
{
    decimalResult = decimalResult / 10;
}
return decimalResult;

Trả về 789,5


-2

Cắt ngắn Zeros rất dễ dàng, giải quyết bằng cách sử dụng song công:

        decimal mydecimal = decimal.Parse("1,45000000"); //(I)
        decimal truncate = (decimal)(double)mydecimal;   //(II)

(I) -> Phân tích giá trị thập phân từ bất kỳ nguồn chuỗi nào.

(II) -> Đầu tiên: Đúc để nhân đôi số 0 này. Thứ hai: Truyền khác sang thập phân vì không tồn tại chuyển đổi ngầm định từ thập phân sang kép và ngược lại)


5
Bạn giả sử tất cả các giá trị sẽ khớp với số thập phân, khớp với số kép. Điều này có thể gây ra OverflowExecellect. Bạn cũng có thể mất độ chính xác.
Martin Mulder

-2

thử mã này:

string value = "100";
value = value.Contains(".") ? value.TrimStart('0').TrimEnd('0').TrimEnd('.') : value.TrimStart('0');

Tại sao hai câu trả lời, bạn của tôi?
Raging Bull

2
Còn những địa phương không sử dụng '.' Thì sao?
Martin Mulder

hoàn toàn không phải là một lựa chọn so với các phương pháp khác trong bài viết này. Chuyển đổi thành chuỗi và trở lại luôn là lựa chọn tồi để thao túng các con số (ít nhất là vì miền địa phương)
Vladimir Semashkin

-11

thử như thế này

string s = "2.4200";

s = s.TrimStart('0').TrimEnd('0', '.');

và sau đó chuyển đổi nó để nổi


1
bạn có thể sử dụng subString()phương pháp cho điều đó, nhưng theo câu hỏi được đăng ở đây, tôi không thấy bất kỳ yêu cầu nào như thế =)
Singleton

2
Còn những địa phương không sử dụng '.'
Dave Hillier

10
Điều này thất bại thảm hại cho các số là bội số của 10.0.
Ben Voigt

1
Những gì @BenVoigt nói là hoàn toàn chính xác, vì một bài kiểm tra "12300.00"sẽ được cắt bớt "123". Một hiệu ứng khác có vẻ không mong muốn là một số số, giống như "0.00"được cắt xén tất cả các chuỗi trống ""(mặc dù số này là trường hợp đặc biệt là "bội số của 10,0").
Jeppe Stig Nielsen
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.