ลบเลขศูนย์ต่อท้าย


177

ฉันมีบางฟิลด์ที่ส่งคืนโดยคอลเล็กชันเป็น

2.4200
2.0044
2.0000

ฉันต้องการผลลัพธ์เช่น

2.42
2.0044
2

ฉันลองด้วยString.Formatแต่มันกลับมา2.0000และตั้งค่าให้N0ปัดเศษค่าอื่นเช่นกัน


3
ประเภทระเบียนเริ่มแรกคือสตริง ??
ซิงเกิลที่

2
ดูคำตอบของฉัน: String.Format()ด้วย 'G' ควรได้รับสิ่งที่คุณต้องการ .. ฉันได้อัปเดตคำตอบพร้อมลิงก์ไปยังรูปแบบตัวเลขมาตรฐานแล้ว userful มาก
หูสุนัข

3
ทศนิยมสามารถถูกโยนไปdoubleและค่าเริ่มต้นToStringสำหรับการปล่อยสองศูนย์ต่อท้าย อ่านนี้
Shimmy Weitzhandler

2
และอาจมีค่าใช้จ่ายน้อยกว่าประสิทธิภาพ (ช่วงของเร็กคอร์ดจำนวนมาก) มากกว่าการส่งผ่าน "G" เป็นรูปแบบสตริงไปยังToStringฟังก์ชัน
Shimmy Weitzhandler

4
คุณไม่ควรแปลงทศนิยมให้เป็นสองเท่ามันจะสูญเสียความสำคัญและอาจแนะนำพลังของความไม่ถูกต้องในการปัดเศษสองครั้ง
kristianp

คำตอบ:


167

มันไม่ง่ายอย่างนี้ถ้าอินพุตเป็นสตริงหรือไม่? คุณสามารถใช้หนึ่งในเหล่านี้:

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

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

2.0m.ToString("G29")

สิ่งนี้ควรใช้กับอินพุตทั้งหมด

อัปเดตตรวจสอบรูปแบบตัวเลขมาตรฐานฉันต้องตั้งค่าตัวระบุความแม่นยำเป็น 29 อย่างชัดเจนเนื่องจากเอกสารระบุอย่างชัดเจน:

อย่างไรก็ตามถ้าตัวเลขเป็นทศนิยมและตัวระบุความแม่นยำถูกละเว้นเครื่องหมายจุดคงที่จะใช้เสมอและเลขศูนย์ต่อท้ายจะถูกเก็บไว้

อัพเดท Konrad ชี้ให้เห็นในความคิดเห็น:

ระวังค่าเช่น 0.000001 รูปแบบ G29 จะนำเสนอด้วยวิธีที่สั้นที่สุดเท่าที่จะเป็นไปได้ดังนั้นจึงจะเปลี่ยนเป็นสัญลักษณ์แบบเอ็กซ์โปเนนเชียล string.Format("{0:G29}", decimal.Parse("0.00000001",System.Globalization.CultureInfo.GetCultureInfo("en-US")))จะให้ผลลัพธ์เป็น "1E-08"


1
จากคำตอบทั้งหมดคุณมีขั้นตอนที่เกี่ยวข้องน้อยที่สุด ขอบคุณหูสุนัข
Zo มี

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

3
@ Dave Hillier - ฉันเข้าใจแล้วฉันได้แก้ไขคำตอบแล้ว ไชโย [เพิ่มชัดเจน 'ตัวระบุความแม่นยำ' อย่างชัดเจน]
Dog Ears

16
ระวังค่าเช่น 0.000001 รูปแบบ G29 จะนำเสนอด้วยวิธีที่สั้นที่สุดเท่าที่จะเป็นไปได้ดังนั้นจึงจะเปลี่ยนเป็นสัญลักษณ์แบบเอ็กซ์โปเนนเชียล string.Format ("{0: G29}", decimal.Parse ("0.00000001", System.Globalization.CultureInfo.GetCultureInfo ("en-US"))) จะให้ "1E-08" เป็นผลลัพธ์
Konrad

15
@ Konrad - มีวิธีการหลีกเลี่ยงสัญลักษณ์ทางวิทยาศาสตร์สำหรับตัวเลขที่มีทศนิยม 5 หรือ 6 ตำแหน่งหรือไม่?
จิลล์

202

ฉันพบปัญหาเดียวกัน แต่ในกรณีที่ฉันไม่สามารถควบคุมเอาต์พุตไปยังสตริงได้ซึ่งไลบรารีได้รับการดูแล หลังจากดูรายละเอียดในการใช้งานประเภททศนิยม (ดูที่http://msdn.microsoft.com/en-us/library/system.decimal.getbits.aspx ) ฉันคิดขึ้นมาอย่างประณีต (นี่เป็นส่วนเสริม วิธี):

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

ส่วนเลขชี้กำลังของทศนิยมจะลดลงเหลือเพียงส่วนที่ต้องการ การเรียก ToString () บนทศนิยมเอาท์พุทจะเขียนหมายเลขโดยไม่มีการต่อท้าย 0 เช่น

1.200m.Normalize().ToString();

29
คำตอบนี้เป็นเจ้าของเพราะแตกต่างกันโดยทั่วไปทุกคำตอบอื่น ๆ ในคำถามนี้ (และแม้กระทั่งเรื่องทั้งหมด) เป็นงานจริงและทำในสิ่งที่ OP ขอ
Coxy

2
จำนวน 0 เป็นปริมาณที่แน่นอนที่นี่หรือเพียงแค่ครอบคลุมค่าที่คาดหวังมากที่สุด
Simon_Weaver

3
MSDN ระบุว่า "ตัวคูณสเกลคือหมายเลข 10 ซึ่งเพิ่มขึ้นเป็นเลขชี้กำลังตั้งแต่ 0 ถึง 28" ซึ่งฉันเข้าใจว่าเลขทศนิยมจะมีจำนวนสูงสุด 28 หลักผ่านจุดทศนิยม จำนวนศูนย์ใด ๆ > = 28 ควรใช้งานได้
โทมัสมาเตน่า

2
นี่คือคำตอบที่ดีที่สุด! จำนวนในคำตอบที่ 34 มีตัวเลขที่1ตามมาด้วย 33 0-s แต่ที่สร้างเหมือนกันdecimalเช่นเป็นตัวเลขโดยมี 29 ตัวเลขหนึ่ง1และ 28 0-s เช่นเดียวกับ @ThomasMaterna พูดในความคิดเห็นของเขา ไม่System.Decimalสามารถมีตัวเลขได้มากกว่า 29 ตัว (ตัวเลขที่มีตัวเลขนำหน้ามากกว่าตัวเลข79228...มีเพียง28 ตัวเท่านั้น) ถ้าคุณต้องการที่มากขึ้นต่อท้ายเลขคูณด้วย1.000...mแทนการแบ่ง นอกจากนี้ยังMath.Roundสามารถตัดเลขศูนย์บางตัวออกเช่นMath.Round(27.40000m, 2)ให้27.40mเหลือเพียงศูนย์เดียว
Jeppe Stig Nielsen

2
เคล็ดลับที่ยอดเยี่ยม แต่ไม่สามารถใช้งานกับ Mono ได้และไม่รับประกันว่าจะสามารถทำงานกับ. NET ได้ในเวอร์ชั่นฟีเจอร์
Bigjim

87

ในความคิดของฉันที่ปลอดภัยในการใช้งานที่กำหนดเองตัวเลขสตริงรูปแบบ

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

25
+1 สำหรับคำตอบเดียวที่ต้องอาศัยพฤติกรรมที่มีความเสถียรและบันทึกไว้
sinelaw

3
คุณควรใส่มี 28 '#' ตัวอักษรดูblackwasp.co.uk/DecimalTrailingZeroes.aspx
Jaime Hablutzel

32

ฉันใช้รหัสนี้เพื่อหลีกเลี่ยงสัญลักษณ์ทางวิทยาศาสตร์ "G29":

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

แก้ไข: การใช้ระบบ CultureInfo.NumberFormat.NumberDecimalSeparator:

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
นี่คือคำตอบที่ยอดเยี่ยม มันง่ายมากและคุณสามารถเห็นสิ่งที่เกิดขึ้นแทนที่จะใช้ฟอร์แมตสตริงเวทมนต์
Timothy Gonzalez

9
ดีมาก แต่ใช้ไม่ได้กับวัฒนธรรมที่ใช้เครื่องหมายจุลภาคสำหรับตัวคั่นทศนิยม คุณต้องใช้Culture.NumberFormat.NumberDecimalSeparator
blearyeye

1
แนวทางที่ดีที่สุด ทุกสิ่งทุกอย่างมีความซับซ้อนโดยไม่จำเป็น เพียงจำไว้เสมอเพื่อตรวจสอบว่าหมายเลขของคุณมีจุดทศนิยม
RRM

1
ในการเป็นส่วนขยายหายไป "นี้" ก่อนพารามิเตอร์: สาธารณะคงที่สตริง DecimalToString (ธันวาคมทศนิยมนี้)
João Antunes

ขอบคุณมากสำหรับความคิดเห็น ฉันได้อัปเดตคำตอบด้วยเวอร์ชันใหม่พร้อมคำแนะนำแล้ว
x7BiT

19

ใช้#สัญลักษณ์hash ( ) เพื่อแสดง 0 ต่อท้ายเมื่อจำเป็นเท่านั้น ดูการทดสอบด้านล่าง

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
ไม่ใช่คำตอบ คุณไม่ได้ลบเลขศูนย์ต่อท้ายคุณกำลังลบความแม่นยำ วิธีที่เสนอของคุณnum1.ToString("0.##")ควรกลับมา13.1534545765(ไม่มีการเปลี่ยนแปลง) เนื่องจากไม่มีศูนย์ต่อท้าย
Jan 'splite' K.

และนั่นคือเหตุผลที่ฉันแสดงคำตอบสำหรับอินพุตสามข้อเสนอของฉัน
Fizzix

มันไม่ได้ตอบคำถามแม้ว่าคุณจะระบุรายการที่นำเสนอ
Dave Friedel

2
id ขึ้นโหวต 10 ครั้งนี้ถ้าฉันทำได้ สิ่งที่ฉันต้องการ!
SubqueryCrunch

1
คำตอบที่สมบูรณ์แบบสำหรับคำถาม คำตอบที่ดีที่สุดในความคิดของฉัน ความคิดเห็นที่ลบความแม่นยำนั้นถูกต้อง แต่นั่นไม่ใช่ quesiton สำคัญที่สุด - เป็นสิ่งที่ฉันต้องการ โดยทั่วไปผู้ใช้ของฉันจะป้อนตัวเลขทั้งหมดอาจจะเป็น 2.5 แต่ฉันต้องรองรับตัวเลข 3 หลักที่เกินจุดทศนิยม ดังนั้นฉันจึงต้องการให้สิ่งที่พวกเขาป้อนไม่ใช่กับศูนย์ที่พวกเขาไม่ได้ป้อน เช่น Console.Write ($ "num3 = {num3: 0. ##}"); => num3 = 30
bobwki

13

ฉันพบโซลูชันที่สวยงามจากhttp://dobrzanski.net/2009/05/14/c-decimaltostring-and-how-to-get-rid-of-traos/

เป็นพื้น

decimal v=2.4200M;

v.ToString("#.######"); // Will return 2.42. The number of # is how many decimal digits you support.

1
โปรดทราบว่าถ้าvเป็นผลของรหัสของคุณเป็นสตริงว่างมากกว่า0m "0"
Sam

2
ใช่. ควรเป็น "0 ########"
PRMan

2

วิธีการระดับต่ำมาก แต่ฉันเชื่อว่านี่จะเป็นวิธีที่มีประสิทธิภาพมากที่สุดโดยใช้การคำนวณจำนวนเต็มอย่างรวดเร็วเท่านั้น (และไม่มีวิธีการแยกสตริงที่ช้าและวิธีการไวต่อวัฒนธรรม):

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
ฉันพยายามที่จะไปเส้นทางนี้ แต่ปรับให้ดีขึ้นต่อไปดังนั้นมันจึงเร็วกว่าของคุณมากโดยไม่ต้องแบ่งhiและmid ints (ของคุณaและb) ในทุก ๆ รอบในขณะที่การทำซ้ำถ้าพวกเขาทั้งหมดเป็นศูนย์อยู่แล้ว อย่างไรก็ตามจากนั้นฉันก็พบวิธีแก้ปัญหาที่เรียบง่ายอย่างน่าประหลาดใจที่จะเอาชนะสิ่งที่คุณกับฉันได้อย่างง่ายดาย
Eugene Beresovsky

2

สิ่งนี้จะได้ผล:

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

หรือถ้าค่าเริ่มต้นของคุณคือstring:

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

ให้ความสนใจกับความคิดเห็นนี้


2
@ Damien ใช่และโปรดทราบว่าสำหรับ puroposes เหล่านี้ (คุณจะไม่รู้สึกอะไรเลยนอกจากคุณจะทำพันล้านรายการ) อันดับแรกเพราะ double เร็วกว่าวินาทีเพราะผ่านการจัดรูปแบบสตริงไปยังฟังก์ชัน ToString ประสิทธิภาพมากกว่า ผ่าน params อีกครั้งคุณจะไม่รู้สึกอะไรเลยถ้าคุณไม่ทำงานกับ gazillions of records
Shimmy Weitzhandler

1
คุณไม่จำเป็นต้องระบุ G, cuz double.ToStringลบเลขศูนย์ต่อท้ายโดยค่าเริ่มต้น
Shimmy Weitzhandler

4
ระวังค่าเช่น 0.000001 สิ่งเหล่านี้จะถูกนำเสนอในรูปแบบเลขชี้กำลัง double.Parse ("0.00000001", System.Globalization.CultureInfo.GetCultureInfo ("en-US")). ToString () จะให้ "1E-08" เป็นผลลัพธ์
Konrad

17
อย่าทำอย่างนี้เลย โดยปกติแล้วเหตุผลที่คุณมีทศนิยมก็เพราะคุณแสดงตัวเลขได้อย่างแม่นยำ (ไม่เหมือนกับที่ประมาณสองเท่า) ได้รับข้อผิดพลาดจุดนี้ลอยอาจจะมีขนาดเล็กสวย แต่อาจส่งผลในการแสดงตัวเลขที่ไม่ถูกต้องไม่มีที่น้อย
อดัม Tegen

2
อย่างไรก็ตามการแปลงประเภทข้อมูล 128 บิต (ทศนิยม) เป็นประเภทข้อมูล 64 บิต (สองเท่า) สำหรับการจัดรูปแบบไม่ใช่ความคิดที่ดี!
avl_sweden

2

มันง่ายมาก

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

ผ่านการทดสอบ

ไชโย :)


1

ขึ้นอยู่กับว่าหมายเลขของคุณเป็นอย่างไรและคุณต้องการจัดการค่าอย่างไร: เป็นสกุลเงินคุณต้องการปัดเศษหรือตัดปลายคุณต้องการปัดเศษนี้เพื่อแสดงหรือไม่

หากการแสดงพิจารณาพิจารณาการจัดรูปแบบตัวเลขเป็น x.ToString ("")

http://msdn.microsoft.com/en-us/library/dwhawy9k.aspxและ

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

ถ้าเป็นเพียงการปัดเศษให้ใช้ Math.Round overload ที่ต้องการ MidpointRounding overload

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

หากคุณได้รับค่าจากฐานข้อมูลให้พิจารณาการส่งแทนการแปลง: double value = (ฐานสิบ) myRecord ["columnName"];


0

คุณสามารถตั้งค่าเป็น:

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

1
ในการทำงานคุณควรใส่ตัวอักษรยี่สิบสี่ตัวแทนที่จะเป็นสองตัว
Jaime Hablutzel

ใช่ฉันเข้าใจผิดคำถามของเขา ... = /
Danilo Ferreira

0

ในกรณีที่คุณต้องการเก็บตัวเลขทศนิยมให้ลองตัวอย่างต่อไปนี้:

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

0

พยายามทำโซลูชันที่เป็นมิตรกับ DecimalToString ( 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());
}

เอาท์พุท:

=>1
=>1.000000023
=>1.000000023
=>

-1

คำตอบที่ง่ายมากคือการใช้ TrimEnd () นี่คือผลลัพธ์

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

เอาต์พุตคือ 1 ถ้าค่าของฉันคือ 1.01 ดังนั้นเอาต์พุตของฉันจะเป็น 1.01


4
สิ่งที่เกี่ยวกับถ้าvalue = 100?
Stephen Drew

4
@Raj De Inno แม้ว่าค่าเป็น 1.00 เอาต์พุตที่ให้คือ "1. " ไม่ใช่ "1"
Simba

-1

รหัสต่อไปนี้สามารถใช้เพื่อไม่ใช้ชนิดสตริง:

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

ส่งคืน 789.5


-2

ตัดศูนย์ที่ต่อท้ายง่ายมากแก้ไขด้วยการเพล็กซ์:

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

(I) -> แยกวิเคราะห์ค่าทศนิยมจากแหล่งสตริงใด ๆ

(II) -> แรก: ส่งไปที่สองนี้ลบศูนย์ต่อท้าย ที่สอง: คาสต์อื่น ๆ เป็นทศนิยมเพราะไม่มีการแปลงโดยนัยจากทศนิยมเป็นสองเท่าและเป็นตัวแทน)


5
คุณถือว่าค่าทั้งหมดที่จะพอดีในทศนิยมพอดีในสองครั้ง สิ่งนี้อาจทำให้เกิดการ OverflowExeception คุณอาจสูญเสียความแม่นยำ
Martin Mulder

-2

ลองรหัสนี้:

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

ทำไมสองคำตอบเพื่อนของฉัน
Raging Bull

2
สถานที่ที่ไม่ได้ใช้ '.' เกี่ยวกับอะไร
Martin Mulder

ไม่ใช่ตัวเลือกเลยเมื่อเปรียบเทียบกับวิธีการอื่น ๆ ภายในโพสต์นี้ การแปลงเป็นสตริงและแบ็กเสมอเป็นตัวเลือกที่ไม่ดีในการจัดการกับตัวเลข (อย่างน้อยก็เพราะตำแหน่งที่ตั้ง)
Vladimir Semashkin

-11

ลองแบบนี้

string s = "2.4200";

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

แล้วแปลงมันให้ลอย


1
คุณสามารถใช้subString()วิธีการนั้น แต่ตามคำถามที่โพสต์ที่นี่ฉันไม่เห็นความต้องการใด ๆ เช่นนั้น =)
Singleton

2
เกี่ยวกับสถานที่ที่ไม่ได้ใช้ '.'
Dave Hillier

10
สิ่งนี้ล้มเหลวอย่างน่าสังเวชสำหรับตัวเลขที่เป็นทวีคูณของ 10.0
Ben Voigt

1
อะไร @BenVoigt กล่าวว่าถูกต้องอย่างสิ้นเชิงเป็น examle จะถูกตัดออกไป"12300.00" "123"ผลกระทบอื่น ๆ ที่ดูเหมือนว่าไม่พึงประสงค์ก็คือตัวเลขบางตัวเช่น"0.00"ถูกตัดออกไปจนถึงสตริงที่ว่างเปล่า""(แม้ว่าตัวเลขนี้จะเป็นกรณีพิเศษของการเป็นส่วนประกอบ "คูณ 10.0")
Jeppe Stig Nielsen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.