简体   繁体   中英

Remove trailing zeros

I have some fields returned by a collection as

2.4200
2.0044
2.0000

I want results like

2.42
2.0044
2

I tried with String.Format , but it returns 2.0000 and setting it to N0 rounds the other values as well.

I ran into the same problem but in a case where I do not have control of the output to string, which was taken care of by a library. After looking into details in the implementation of the Decimal type (see http://msdn.microsoft.com/en-us/library/system.decimal.getbits.aspx ), I came up with a neat trick (here as an extension method):

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

The exponent part of the decimal is reduced to just what is needed. Calling ToString() on the output decimal will write the number without any trailing 0. Eg

1.200m.Normalize().ToString();

Is it not as simple as this, if the input IS a string? You can use one of these:

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

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

2.0m.ToString("G29")

This should work for all input.

Update Check out the Standard Numeric Formats I've had to explicitly set the precision specifier to 29 as the docs clearly state:

However, if the number is a Decimal and the precision specifier is omitted, fixed-point notation is always used and trailing zeros are preserved

Update Konrad pointed out in the comments:

Watch out for values like 0.000001. G29 format will present them in the shortest possible way so it will switch to the exponential notation. string.Format("{0:G29}", decimal.Parse("0.00000001",System.Globalization.CultureInfo.GetCultureInfo("en-US"))) will give "1E-08" as the result.

In my opinion its safer to use Custom Numeric Format Strings .

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

I use this code to avoid "G29" scientific notation:

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

EDIT: using system 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;
}

Use the hash ( # ) symbol to only display trailing 0's when necessary. See the tests below.

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%

I found an elegant solution from http://dobrzanski.net/2009/05/14/c-decimaltostring-and-how-to-get-rid-of-trailing-zeros/

Basically

decimal v=2.4200M;

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

A very low level approach, but I belive this would be the most performant way by only using fast integer calculations (and no slow string parsing and culture sensitive methods):

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

This is simple.

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

Tested.

Cheers :)

Depends on what your number represents and how you want to manage the values: is it a currency, do you need rounding or truncation, do you need this rounding only for display?

If for display consider formatting the numbers are x.ToString("")

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

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

If it is just rounding, use Math.Round overload that requires a MidPointRounding overload

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

If you get your value from a database consider casting instead of conversion: double value = (decimal)myRecord["columnName"];

Trying to do more friendly solution of 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());
}

Output:

=>1
=>1.000000023
=>1.000000023
=>

how about this:

public static string TrimEnd(this decimal d)
    {
        string str = d.ToString();
        if (str.IndexOf(".") > 0)
        {
            str = System.Text.RegularExpressions.Regex.Replace(str.Trim(), "0+?$", " ");
            str = System.Text.RegularExpressions.Regex.Replace(str.Trim(), "[.]$", " ");
        }
        return str;
    }

You can just set as:

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

This will work:

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

Or if your initial value is string :

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

Pay attention to this comment .

The following code could be used to not use the string type:

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

Returns 789.5

如果您想保留十进制数,请尝试以下示例:

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

Here is an Extention method I wrote, it also removes dot or comma if it`s the last character (after the zeros were removed):

public static string RemoveZeroTail(this decimal num)
{
    var result = num.ToString().TrimEnd(new char[] { '0' });
    if (result[result.Length - 1].ToString() == "." || result[result.Length - 1].ToString() == ",")
    {
        return result.Substring(0, result.Length - 1);
    }
    else
    {
        return result;
    }
}

要从字符串变量dateTicks中删除尾随零,请使用

return new String(dateTicks.Take(dateTicks.LastIndexOf(dateTicks.Last(v => v != '0')) + 1).ToArray());

Additional Answer:

In a WPF Application using XAML you could use

{Binding yourDecimal, StringFormat='#,0.00#######################'}

The above answer will preserve the zero in some situations so you could still return 2.00 for example

{Binding yourDecimal, StringFormat='#,0.#########################'}

If you want to remove ALL trailing zeros, adjust accordingly.

The following code will be able to remove the trailing 0's. I know it's the hard way but it works.

private static string RemoveTrailingZeros(string input) 
{
    for (int i = input.Length - 1; i > 0; i-- )
    {
        if (!input.Contains(".")) break;
        if (input[i].Equals('0'))
        {
            input= input.Remove(i);
        }
        else break;
    }
    return input;
}
string.Format("{0:G29}", decimal.Parse("2.00"))

在此处输入图像描述

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

Truncate trailing Zeros is very easy, resolve with a duplex cast:

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

(I) --> Parse decimal value from any string source.

(II) --> First: Cast to double this remove the trailing zeros. Second: Other cast to decimal because dont exist implicit conversion from decimal to double and viceversa)

try this code:

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

Very simple answer is to use TrimEnd(). Here is the result,

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

Output is 1 If my value is 1.01 then my output will be 1.01

try like this

string s = "2.4200";

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

and then convert that to float

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM