【问题标题】:Converting exponential number to decimal 1.11111117E+9 - trailing digits become zero将指数数转换为十进制数 1.11111117E+9 - 尾随数字变为零
【发布时间】:2011-01-18 11:31:51
【问题描述】:

我正在尝试转换指数数字 1.11111117E+9,它实际上是一个 10 位数字“1111111111”。当我尝试使用 decimal.TryParse 方法转换此指数数时,它会将最后 3 位数字设为零并将数字设为“111111000”。任何 10 位数字都会发生这种情况。

   decimal amount;
   decimal.TryParse("1.11111117E+9", NumberStyles.Any, null, out amount);

这很奇怪,但我无法弄清楚这里有什么问题,谁能告诉我这有什么问题?

编辑: 很抱歉这个误导性的问题。正如 Henrik 在他的回答中提到的,这正是我所面临的。

float f = 1111111111;
string s = f.ToString();
decimal amount;
decimal.TryParse(s, NumberStyles.Any, null, out amount);

这将始终返回 1111111000?如何解决此问题以获得正确的值?将其从浮点数据类型更改为 Double 或 Decimal 是解决方案还是其他?

【问题讨论】:

  • '111111111' 是一个 9 位的数字,当然不等于 '1.11111117E+9'。你的问题还很不清楚……
  • 另外值得注意的是,1.11111117E9 将是 1111111170。如果您的源编号精度不足,则需要在末尾添加一些零来填充它。
  • @Jon Skeet:抱歉打错了。已更正。
  • @JPReddy:无论它来自哪里,1.11111117E+9 不是 1111111111。

标签: c# parsing decimal tryparse exponential


【解决方案1】:

往返浮点值很容易...

float f = 1111111111;
string s = f.ToString("r"); // r = roundtrip
float g = float.Parse(s);

现在fg 将是相同的...但这并不意味着任何一个值都恰好是 1111111111...因为该值不能表示为浮点数。可以精确表示为浮点数的最接近的值是 1111111168...这就是为什么您在科学表示的末尾得到 7。

基本上,您首先不应该为此使用float。来自System.Single 的文档:

默认情况下,Single 值仅包含 7 位精度的十进制数字,但内部维护最多 9 位数字。

所以试图存储一个 10 位数字并期望它被准确存储是愚蠢的差事。

很难说你应该使用double 还是decimal - 这取决于你真正想要存储的值。如果它是像体重或身高这样的“自然”值,我会选择double。如果它是像价格这样的“人”值,我会使用decimal

【讨论】:

  • 我认为我将 10 位数的值存储在浮点数中是错误的,这就是所有这些混乱的原因。这是一个财务价值,所以我会选择小数,尽管我需要在性能上做出妥协。
【解决方案2】:

这个

decimal amount;
decimal.TryParse("1.11111117E+9", NumberStyles.Any, 
    CultureInfo.InvariantCulture, out amount);

按预期设置金额为 1111111170M。

注意 CultureInfo.InvariantCulture,因此它不依赖于您的本地设置。

更新:我怀疑你的真实代码看起来像这样:

float f = 1111111111;
string s = f.ToString();
decimal amount;
decimal.TryParse(s, NumberStyles.Any, null, out amount);

f 在调试器中显示为 1.11111117e+9,s 为 1.111111e+9,数量为 1111111000M。 造成这一切的原因是浮点数的精度有限。

【讨论】:

  • 你在我的问题中得到了正确的观点,即使我的问题非常混乱和不正确。您的浮动解释适用于我的问题。是的,这就是我面临的问题。你能解释一下浮点的有限精度吗?在这种情况下我该如何解决这个问题?
【解决方案3】:

试试这个, 对我来说效果更好

 decimal dec = Decimal.Parse("1.11111117E+9", System.Globalization.NumberStyles.Any);

【讨论】:

    【解决方案4】:

    您应该解析double,而不是decimal。科学计数法与decimal 无关。

    更新:确切的整数值是1111111170。不是111111111,它比应有的值少了大约 10 倍。

    【讨论】:

    • 我认为科学记数法实际上比使用双精度数更有意义,因为尾数/指数形式在字符串中的基数与十进制的本机格式相同。
    • 解析双精度或十进制不会返回正确的值。请查看更新后的问题。
    • @JPReddy:您的代码没有正确的开头值,因为它不能用浮点数表示。垃圾进,垃圾出……
    猜你喜欢
    • 2012-04-17
    • 2013-05-31
    • 2018-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 2020-08-06
    相关资源
    最近更新 更多