代码之家  ›  专栏  ›  技术社区  ›  scobi

是否可以以非科学格式格式化浮点?

  •  3
  • scobi  · 技术社区  · 16 年前

    我试图将一个浮点转换为一个字符串,但没有得到科学的(1.13e-8)样式格式。

    我正在寻找一些“f”和“r”说明符的组合。我要的是f,这样它就不使用科学的样式,但我也要的是r,这样它就可以使用尽可能少的空间来精确地表示数字。

    所以给定0.00000001,字符串版本应该是0.00000001。不是1E-09,也不是0.000000001000。

    是否可以告诉系统“固定点,但使用所需的最小数字精确指定数字”?

    如果不是,一个好的解决方法是什么?我在想:使用20的精度,然后在字符串中有“.”的情况下去掉尾随的0。有更好的吗?

    编辑:

    这是我一直使用的版本。我真的希望有一个格式说明符,我可以用它来代替。

    var s = f.ToString("F20");
    if (s.Contains("."))
    {
        s = s.TrimEnd('0').TrimEnd('.');
    }
    
    2 回复  |  直到 16 年前
        1
  •  1
  •   Noldorin    14 年前

    以下仅显示小数点后的有效数字,最多10 d。

    var format = "#0.##########";
    
    string.Format(1.23, format);
    // 1.23
    
    string.Format(1.23456, format);
    // 1.23456
    
    string.Format(1.230045, format);
    // 1.230045
    
    string.Format(1.2345678912345, format);
    // 1.2345678912
    

    这里的关键是 # 能指只输出一个数字,如果它是 重要的 .

    希望这至少能达到你想要的程度。如果没有,则可以始终编写自定义 IFormatProvider .

        2
  •  1
  •   Jason Kresowaty    14 年前

    请注意,“精确指定数字”可能不可能。这个数字可能涉及以2为基数的重复。考虑1/3如何在基数10中重复 0.33333333... . 这也发生在基数2上,只是更糟。但是,您可以使用“r”获得往返的值。

    使用 "F20" 然后修剪 不会 产生的结果与在 "r" 格式。论 Math.PI ,您的代码生成 3.14159265358979 . 往返应该是 3.1415926535897931 .

    例如,下面是如何将小数点移动到 “R” 格式。

    static string FormatMinDigits(double d)
    {
        String r = d.ToString("r", System.Globalization.CultureInfo.InvariantCulture);
        if (Double.IsInfinity(d) || Double.IsNaN(d))
            return r;
        String us = r.TrimStart('-');
        int epos = us.IndexOf('E');
        string mantissa;
        int exponent;
        if (epos == -1)
        {
            mantissa = us;
            exponent = 0;
        }
        else
        {
            mantissa = us.Substring(0, epos);
            exponent = Int32.Parse(us.Substring(epos + 1));
        }
        int dotPos = mantissa.IndexOf('.');
        if (dotPos == -1)
            dotPos = mantissa.Length;
        mantissa = mantissa.Replace(".", "");
        string s;
        if (exponent > 0)
        {
            if (exponent + dotPos - mantissa.Length > 0)
                mantissa += new String('0', exponent + dotPos - mantissa.Length);
            s = mantissa.Insert(exponent + dotPos, ".").TrimEnd('.');
        }
        else if (exponent < 0)
        {
            if (-(exponent + dotPos) > 0)
                mantissa = new String('0', -(exponent + dotPos)) + mantissa;
            s = mantissa.Insert(0, "0.");
        }
        else
            s = mantissa.Insert(dotPos, ".").TrimEnd('.');
        if (d < 0)
            s = '-' + s;
        if (double.Parse(s, System.Globalization.CultureInfo.InvariantCulture) != d) // Since format "r", it should roundtrip.
            throw new Exception(string.Format("Internal error in FormatMinDigits: {0:r}", r));
        return s;
    }