Sondaki sıfırları kaldır


177

Bir koleksiyon tarafından döndürülen bazı alanlar var

2.4200
2.0044
2.0000

Gibi sonuçlar istiyorum

2.42
2.0044
2

İle denedim String.Format, ama geri döner 2.0000ve N0diğer değerleri de yuvarlar.


3
başlangıçta kayıt türü dize ??
Singleton

2
Cevabımı gör: String.Format()'G' ile istediğini almalısın .. Cevabımı standart sayısal formatlara link ile güncelledim. Çok kullanışlıdır.
Köpek Kulakları

3
Ondalık bir ondalık sayıya dönüştürülebilir doubleve ToStringçift için varsayılan değer sondaki sıfırları yayar. okumak bu
Shimmy Weitzhandler

2
Ve muhtemelen "G" yi ToStringfonksiyona bir dize formatı olarak geçirmekten daha az performansa (çok fazla kayıt aralığına) mal olur .
Shimmy Weitzhandler

4
Ondalık sayıyı ikiye dönüştürmemelisiniz, önemini yitirecektir ve iki yuvarlama yanlışlığının gücünü ortaya çıkarabilir.
kristianp

Yanıtlar:


167

Giriş bir dize IS ise, bu kadar basit değil mi? Bunlardan birini kullanabilirsiniz:

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

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

2.0m.ToString("G29")

Bu, tüm girdiler için çalışmalıdır.

Güncelleme Dokümanlar açıkça belirtildiği gibi, kesinlik belirtecini 29 olarak açıkça ayarlamak zorunda kaldığım Standart Sayısal Biçimlere göz atın :

Bununla birlikte, sayı Ondalık ise ve duyarlık belirtici atlanırsa, sabit nokta gösterimi her zaman kullanılır ve sondaki sıfırlar korunur

Konrad Güncellemesi yorumlarda belirtti :

0.000001 gibi değerlere dikkat edin. G29 formatı bunları mümkün olan en kısa şekilde sunacaktır, böylece üstel gösterime geçecektir. string.Format("{0:G29}", decimal.Parse("0.00000001",System.Globalization.CultureInfo.GetCultureInfo("en-US")))sonuç olarak "1E-08" verecektir.


1
Tüm cevaplar arasında, en az adım atmış olmanız. Teşekkür ederim köpek kulaklar.
Zo

4
var d = 2.0m; d.ToString ( "G");
Dave Hillier

3
@Dave Hillier - Anlıyorum, cevabımı düzelttim. Şerefe. [açık 'hassas belirleyici' eklendi]
Köpek Kulakları

16
0.000001 gibi değerlere dikkat edin. G29 formatı bunları mümkün olan en kısa şekilde sunacaktır, böylece üstel gösterime geçecektir. string.Format ("{0: G29}", ondalık. Parse ("0.00000001", System.Globalization.CultureInfo.GetCultureInfo ("en-US"))) sonuç olarak "1E-08" verecektir
Konrad

15
@Konrad - 5 veya 6 ondalık basamağı olan sayılar için Bilimsel gösterimden kaçınmanın bir yolu var mı?
Jill

202

Aynı sorunla karşılaştım ama bir kütüphane tarafından halledilen dizeye çıktı kontrolü olmayan bir durumda. Ondalık türün uygulanmasındaki ayrıntılara baktıktan sonra (bkz. Http://msdn.microsoft.com/en-us/library/system.decimal.getbits.aspx ), düzgün bir numara buldum (burada bir uzantı olarak) yöntem):

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

Ondalık sayının üssü tam olarak gereken şeye indirgenir. Çıktı ondalık biriminde ToString () çağrıldığında, numara herhangi bir iz olmadan 0 yazılır.

1.200m.Normalize().ToString();

29
Bu cevabın sahibi, çünkü bu sorudaki (ve hatta tüm konunun) diğer tüm cevaplarının aksine aslında ÇALIŞIR ve OP'nin sorduğu şeyi yapar.
Coxy

2
0 sayısı burada mı yoksa sadece en çok beklenen değerleri kapsıyor mu?
Simon_Weaver

3
MSDN, "Ölçeklendirme faktörü örtük olarak 10 ile 0'dan 28'e kadar bir üsse yükseltilmiş sayıdır" demektedir. İstediğiniz sayıda sıfır> = 28 olmalıdır.
Thomas Materna

2
Bu en iyi cevap! Cevaptaki sayı 34 rakamdan oluşuyor, 1bunu 33 0-s takip ediyor , ancak bu decimal29 rakamlı, bir 1ve 28- 0s'li rakamlarla tam olarak aynı örneği yaratıyor . Tıpkı @ThomasMaterna'nın yorumunda söylediği gibi. Hayır System.Decimal, 29'dan fazla rakama sahip 79228...olamaz (önde gelen rakamları toplamda sadece 28 rakama sahip olan sayılar) Daha fazla arka sıfır istiyorsanız 1.000...m, bölmek yerine çarpın . Ayrıca, Math.Roundbazı sıfırları doğrayabilir, örneğin Math.Round(27.40000m, 2)verir 27.40m, bu yüzden sadece bir sıfır kaldı.
Jeppe Stig Nielsen

2
Büyük hile ancak Mono üzerinde çalışmaz ve .NET'in özellik sürümlerinde çalışması için
garanti edilmez


32

"G29" bilimsel gösterim önlemek için bu kodu kullanın:

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

EDIT: sistem CultureInfo.NumberFormat.NumberDecimalSeparator kullanarak:

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
Bu harika bir cevap. Çok basit ve sihirli bir dize biçimlendirici kullanmak yerine tam olarak ne olduğunu görebilirsiniz.
Timothy Gonzalez

9
Güzel, ama ondalık ayırıcı için virgül kullanan kültürler için işe yaramaz. Kullanmanız gerekirCulture.NumberFormat.NumberDecimalSeparator
blearyeye

1
En iyi yaklaşım. Diğer her şey gereksiz yere karmaşık. Her zaman numaranızın ondalık basamak içerip içermediğini kontrol etmeyi unutmayın.
RRM

1
Bir uzantı için parametre öncesinde "this" eksik: public static string DecimalToString (this ondalık dec)
João Antunes

Yorumlar için çok teşekkür ederim. Cevabı ipuçlarını içeren yeni bir sürümle güncelledim.
x7BiT

19

#Yalnızca gerektiğinde sondaki 0'ları görüntülemek için hash ( ) sembolünü kullanın. Aşağıdaki testlere bakın.

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
Cevap değil. Sondaki sıfırları kaldırmıyorsunuz, hassasiyeti kaldırıyorsunuz. Sonunda sıfır olmadığı için önerilen yönteminiz (değişiklik yok) num1.ToString("0.##")döndürmelidir 13.1534545765.
Jan 'splite' K.

İşte tam da bu yüzden önerilen üç girişime cevapları gösteriyorum, böylece kullanıcılar benim çözümümün nasıl çalıştığını görebiliyor.
Fizzix

Önerilen girdileri listeleseniz bile soruya cevap vermez.
Dave Friedel

2
Eğer yapabilseydim id bu 10 kez oy. Tam olarak ihtiyacım olan şey!
SubqueryCrunch

1
Sorunun mükemmel cevabı. Bence EN İYİ cevap. Hassasiyeti ortadan kaldırdığını doğru yorumlayın, ancak bu bir sorun değildi. En önemlisi - ihtiyacım olan şey bu. Kullanıcılarım genellikle tam sayıları girecek, belki 2.5 gibi bir şey, ama ondalık noktanın ötesinde 3 basamak desteklemem gerekiyor. Bu yüzden onlara girdikleri şeyi vermek istiyorum, girmedikleri bir grup sıfırla değil. örneğin, Console.Write ($ "num3 = {num3: 0. ##}"); => num3 = 30
bobwki


2

Çok düşük seviyeli bir yaklaşım, ancak bunun sadece hızlı tamsayı hesaplamaları (ve yavaş dize ayrıştırma ve kültüre duyarlı yöntemler yok) kullanarak en performanslı yol olacağını düşünüyorum:

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
Bu rotaya gitmeye çalıştım, ancak daha da optimize ettim, böylece her şeyden önce sıfırsa , hi ve orta ints'ı (sizin ave b) her yinelemede bölmeyerek , sizinkinden çok daha hızlı hale geldi . Ancak o zaman ben ve ben de akıllıca bir performans ortaya çıkardı da kolayca yener bu şaşırtıcı derecede basit bir çözüm buldum .
Eugene Beresovsky

2

Bu çalışacak:

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

Veya başlangıç ​​değeriniz string:

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

Bu yoruma dikkat edin .


2
@Damien, evet ve not edin, bu puropozlar için (bir milyar kayıt yapmadıkça hiçbir şey hissetmeyeceksiniz), ilk olarak çift daha hızlı, ikinci çünkü ToString işlevine bir dize biçimini iletmek, geçen params. Yine, milyonlarca kayıt üzerinde çalışmadığınız sürece hiçbir şey hissetmezsiniz.
Shimmy Weitzhandler

1
G belirtmeniz gerekmez, çünkü double.ToStringvarsayılan olarak sondaki sıfırları kaldırır.
Shimmy Weitzhandler

4
0.000001 gibi değerlere dikkat edin. Bunlar üstel gösterimde sunulacaktır. double.Parse ("0.00000001", System.Globalization.CultureInfo.GetCultureInfo ("en-US")). ToString () sonucu "1E-08" verecek
Konrad

17
Bunu ASLA yapma. Genellikle, ondalık sayıya sahip olmanızın nedeni, bir sayıyı tam olarak temsil etmenizdir (yaklaşık olarak iki katına benzemez). Kabul edilirse, bu kayan nokta hatası muhtemelen oldukça küçüktür, ancak yanlış numaraların görüntülenmesine neden olabilir, hiç de az
Adam Tegen

2
Biçimlendirme için 128 bit veri tipini (ondalık) 64 bit veri tipine (çift) dönüştürmek, iyi bir fikir değil!
avl_sweden

2

Bu basit.

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

Test edilmiştir.

Şerefe :)


1

Numaranızın neyi temsil ettiğine ve değerleri nasıl yönetmek istediğinize bağlıdır: bu bir para birimi mi, yuvarlama mı yoksa kesilmeye mi ihtiyacınız var, bu yuvarlamaya sadece görüntüleme için mi ihtiyacınız var?

Görüntüleme için sayıları biçimlendirmeyi düşünün x.ToString ("")

http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx ve

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

Sadece yuvarlanıyorsa, MidPointRounding aşırı yüklemesi gerektiren Math.Round aşırı yükünü kullanın

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

Değerinizi bir veritabanından alırsanız, dönüşüm yerine döküm yapmayı düşünün: double value = (ondalık) myRecord ["columnName"];


0

Sadece şu şekilde ayarlayabilirsiniz:

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

1
Bunun işe yaraması için sadece iki yerine yirmi sekiz '#' karakteri koymalısınız.
Jaime Hablutzel

Evet, sorusunu yanlış anladım ... = /
Danilo Ferreira

0

Ondalık sayıyı korumak istiyorsanız, aşağıdaki örneği deneyin:

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

0

Daha kolay DecimalToString çözümü yapmaya çalışıyorum ( https://stackoverflow.com/a/34486763/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());
}

Çıktı:

=>1
=>1.000000023
=>1.000000023
=>

-1

Çok basit cevap TrimEnd () kullanmaktır. İşte sonuç,

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

Çıktı 1 ise Değerim 1.01 ise çıktım 1.01 olacak


4
Ne olur value = 100?
Stephen Drew

4
@Raj De Inno Değer 1.00 olsa bile verdiği çıktı "1" dir. "1" değil
Simba

-1

Dize türünü kullanmamak için aşağıdaki kod kullanılabilir:

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

789,5 döndürür


-2

Sondaki Zeros'u kısaltmak çok kolaydır, dubleks bir dökümle çözün:

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

(I) -> Herhangi bir dize kaynağından ondalık değeri ayrıştırın.

(II) -> İlk: Sondaki sıfırları kaldırmak için bunu iki katına çıkarın. İkincisi: Ondalıktan ikiye ve viceversa'ya örtük dönüşüm olmadığı için diğer ondalık sayıya dökülür)


5
Ondalık, çift olarak sığacak tüm değerleri varsayarsınız. Bu bir Taşma Bekletmesine neden olabilir. Ayrıca hassasiyeti kaybedebilirsiniz.
Martin Mulder

-2

bu kodu deneyin:

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

Neden iki cevap arkadaşım?
Raging Bull

2
'.' Kullanmayan yerel ayarlara ne dersiniz?
Martin Mulder

bu yazıdaki diğer yaklaşımlarla karşılaştırıldığında hiç bir seçenek değil. Dize ve arkaya dönüştürme sayıları manipüle etmek için her zaman kötü bir seçenektir (en azından yerel ayar nedeniyle)
Vladimir Semashkin

-11

böyle dene

string s = "2.4200";

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

ve sonra bunu şamandıraya dönüştür


1
Bunun için subString()yöntem kullanabilirsiniz , ancak burada yayınlanan soruya göre, böyle bir gereklilik görmüyorum =)
Singleton

2
'.' Kullanmayan yerel ayarlara ne dersiniz?
Dave Hillier

10
Bu, 10.0'ın katları olan sayılar için sefil bir şekilde başarısız olur.
Ben Voigt

1
@BenVoigt'ın söyledikleri tamamen doğrudur, çünkü bir sınav "12300.00"kesilecektir "123". İstenmeyen görünen bir diğer etki, bazı sayıların, örneğin "0.00"boş dizeye ""kadar kesilmiş olmasıdır (bu sayı , "10.0'ın katları" olarak ayrılmaz özel bir durum olsa da ).
Jeppe Stig Nielsen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.