【问题标题】:c# - Issue with rounding of decimals when integral part is greater than 9 charactersc# - 当整数部分大于 9 个字符时,小数舍入问题
【发布时间】:2019-07-24 12:49:57
【问题描述】:

在 C# 中,将 double 类型数字转换为整数部分包含 9 个或更少字符的字符串类型会给出正确的值。但是将整数部分改成大于9的字符,得到的结果却不尽如人意。

例如,

123456789.123456789 结果“123456789.1235”(四舍五入到小数点后 4 位)是正确的。

但是,1234567891111.123456789,结果“1234567891111.1200”是错误的。

预期输出为“1234567891111.1235”。

下面是我尝试过两次修复的代码,但没有一个给出所需的输出。

using System;
using System.Globalization;

public class Program
{
    public static void Main()
    {
        double sample = 0.0;
        string fieldText = "1234567891111.12345678";

    // Fix 1
    double.TryParse(fieldText,System.Globalization.NumberStyles.Any, CultureInfo.CurrentCulture, out sample);
    Console.WriteLine(sample); // 1234567891111.12

    // Fix 2
    string FormattedText = string.Format(CultureInfo.InvariantCulture, "{0:0.0000}", 1234567891111.123446789);
    Console.WriteLine(FormattedText); // 1234567891111.1200

    // Expected output - 1234567891111.1235

    }
}

请推荐,

  1. 如何正确舍入小数,整数部分具有更多字符 (>9),如示例中所述?
  2. 另外,Double类型转字符串时如何显示完整的数字(1234567891111.123456789)而不是科学计数法(1.23456789111112E+21)?

提前致谢。

【问题讨论】:

  • 没有所谓的“正确”舍入。有不同类型的舍入,我建议您阅读该主题,特别是 .NET 使用的类型。
  • 除了 Caius Jard 所说的,这是正确的,浮点并没有对所有值都有精确的表示,实际上有无限数量的“非整数”值不能表示为浮点数的精确值。
  • string FormattedText = string.Format(CultureInfo.InvariantCulture, "{0:E12}", 1234567891111.123446789M); 可能值得一试。
  • var rounded = Math.Round(1234567891111.123446789, 4); string formattedText = rounded.ToString("R4");string formattedText = string.Format(CultureInfo.InvariantCulture, "{0:R4}", 1234567891111.123446789);

标签: c# .net


【解决方案1】:

double 类型只能存储一定精度的浮点数(约 15 位有效数字)。数字 1234567891111.12345678 太精确,无法存储在 double 中。 double 只能存储精确到 1234567891111.12 的内容。

解决此问题的一种方法是使用比double 更精确的类型:decimal

通过在文字末尾添加m,文字变为decimal 文字:

string FormattedText = string.Format(
    CultureInfo.InvariantCulture, 
    "{0:0.0000}", 
    1234567891111.123446789m);
Console.WriteLine(FormattedText);

显然,decimal 也只能达到一定的精度。

【讨论】:

    【解决方案2】:

    但是,1234567891111.123456789,结果“1234567891111.1200”是错误的。 预期输出为“1234567891111.1235”。

    是的,但是双精度数不能存储那么多数字。 The Fine Manual 表示 double 适合 15 位数字,而 1234567891111.12 是 15 位数字。之后您尝试像这样制作 double:

    double d = 1234567891111.1234
    

    导致你的替身实际上只跟踪这个:

    double d = 1234567891111.12;
    

    因此,当您将其格式化为 4 位小数时,它将打印 1234567891111.1200

    这与双精度数的大小(大小)无关,而与位数有关。尝试将1.000 0000 0000 0000 0001(20 位数字)存储在一个双精度中是行不通的,那个双精度将是 1

    【讨论】:

      【解决方案3】:

      double 类型没有足够的空间来存储这么多数字。请改用 Decimal 类型。

      Decimal sample = 0.0M;
      string fieldText = "1234567891111.12345678";
      
      Decimal.TryParse(fieldText, System.Globalization.NumberStyles.Any, CultureInfo.InvariantCulture, out sample);
      
      string FormattedText = string.Format(CultureInfo.InvariantCulture, "{0:0.0000}", sample);
      Console.WriteLine(FormattedText);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-08-10
        • 2020-09-17
        • 1970-01-01
        • 2011-05-13
        • 2016-11-03
        • 1970-01-01
        • 1970-01-01
        • 2021-09-13
        相关资源
        最近更新 更多