我有一些由集合返回的字段

2.4200
2.0044
2.0000

我想要这样的结果

2.42
2.0044
2

我试过用String。格式,但它返回2.0000,并将其设置为N0也会四舍五入其他值。


当前回答

一个非常低级的方法,但我相信这将是最高效的方法,只使用快速整数计算(没有缓慢的字符串解析和区域性敏感的方法):

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

其他回答

我遇到了同样的问题,但在我无法控制输出到字符串的情况下,这是由库处理的。在详细了解了Decimal类型的实现(参见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();

要从字符串变量dateTicks中删除后面的零,请使用

返回新的字符串(dateTicks.Take(dateTicks.LastIndexOf(dateTicks.Last(v => v != '0')) + 1)。ToArray());

这个怎么样:

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

这是我写的一个扩展方法,如果它是最后一个字符(在0被删除之后),它也会删除点或逗号:

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

如果输入是一个字符串,它不是这么简单吗?你可以使用其中一个:

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

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

2.0m.ToString("G29")

这应该适用于所有输入。

我必须显式地将精度说明符设置为29,因为文档清楚地声明:

但是,如果数字是Decimal且省略了精度说明符,则始终使用定点表示法并保留后面的零

Konrad在评论中指出:

注意像0.000001这样的值。G29格式将以最短的方式表示它们,因此它将切换到指数符号。字符串。Format("{0:G29}", decimal.Parse("0.00000001",System.Globalization.CultureInfo.GetCultureInfo("en-US")))将给出"1E-08"作为结果。