【问题标题】:How to format a double with as many as significant digits as possible?如何用尽可能多的有效数字格式化双精度数?
【发布时间】:2011-09-17 21:54:33
【问题描述】:

我想用 尽可能多的数字 格式化一个双精度值,以保持相同的值。 我确实想使用指数表示法,因为字符串的接收者需要浮点表示法。

例子:

12.0 -> "12"
12.20300 -> "12.203"

编辑: Round-trip specifier "R" 似乎可以满足我的需要。至少对于我测试的数字,它按预期工作。

【问题讨论】:

  • 为什么不能使用printf( "%d" )?据我所知,它不会将任何尾随或前导零放在双精度数上。
  • 因为我上次检查时,C 不是受支持的 CLR 语言 :)
  • @cody,似乎double.ToString() 已经省略了尾随的 0,还是您发现不同?或者您是否使用了其他类型,例如decimal?我已删除我的答案,等待更多信息。
  • @Anthony Pegram: double.ToString() 在某些情况下可能会返回指数符号,这不是我想要的。
  • 您正在与需要将浮点值格式化为 string 的代码进行互操作?这不可能……

标签: .net formatting floating-point tostring number-formatting


【解决方案1】:

您可以使用String.Format 和自定义格式字符串来告诉格式化程序以您想要的方式打印它。在这种情况下,您希望使用类似于0.################ 的修饰符。此格式化程序实质上指定该数字应在小数点前至少有一位数字,并且在小数点后最多(但不一定)十六位数字。不幸的是,您必须有一个最大值,以# 符号的数量表示,但 16 应该绰绰有余。

String.Format("{0:0.################}", 12.20300);

【讨论】:

    【解决方案2】:

    Format(x, "0.###############") 非常接近,但是在使cDbl(Format(x, "0.################")) <> x 为大多数分数。

    您可以通过这种方式在小数点右侧获得更多数字,但这并不实用(因为它们是垃圾数字)并且可能不是您想要的:

    For i = 1 To ndigits
      s = s & Math.Floor(x * (10 ^ i)) Mod 10
    Next i
    

    即使这样,您也可能无法从 double 转换为 string 再转换回 double,并使它们相等。我知道这样做的唯一方法是科学记数法或十六进制。

    【讨论】:

      【解决方案3】:

      真的做不到。无论如何都不是微不足道的,也不使用Doubles。双精度数根本没有 足够的数字让您显示任何数字,这可能就是为什么在您简单地调用 .ToString() 时使用科学计数法来显示值的原因

      我们得到的双精度数的输出是科学计数法,因为它更好地代表了值。以这段代码为例....

          double testValue = 9123456789012345678.234;
          string formatStr = "{0:0.####################################################},{1}";
          Debug.WriteLine(String.Format(formatStr, testValue, testValue));
      

      我们得到的输出是:

      9123456789012350000,9.12345678901235E+18

      我们开始时的实际数字也不是。如果您忽略非常大的数字,我想您会发现您发布的示例不需要您做任何事情。

       Debug.WriteLine(12.0d + " == " + String.Format("{0} == {1:0.########################}",  12.0d, 12.0d));
       Debug.WriteLine(12.20300d + " == " + String.Format("{0} == {1:0.########################}", 12.20300d, 12.20300d));
       Debug.WriteLine(-00.2900d + " == " + String.Format("{0} == {1:0.########################}", -00.2900d, -00.2900d));
       Debug.WriteLine(99999999999999999999999d + " == " + String.Format("{0} == {1:0.########################}", 99999999999999999999999d, 99999999999999999999999d));
      
      
      12 == 12 == 12
      12.203 == 12.203 == 12.203
      -0.29 == -0.29 == -0.29
      1E+23 == 1E+23 == 100000000000000000000000
      

      在前三个例子中,无论是直接用WriteLine显示,还是使用不带格式字符串的String.Format,还是使用“0.########”,输出都是你想要的。值不同的唯一情况是在第四种情况下,默认行为是显示科学计数法。更改该行为将为您提供带有额外零的数字,而您期望这些数字是有意义的;但它可以像 Samir 所示的格式字符串那样完成。

      【讨论】:

        猜你喜欢
        • 2013-03-25
        • 2019-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多