【问题标题】:C# Converting Double to Float Loses So Much Precision Why?C# 将 Double 转换为 Float 会损失如此多的精度,为什么?
【发布时间】:2019-06-01 14:15:45
【问题描述】:

当我使用 Visual Studio 调试程序时;

当我通过使用将双变量“91.151497095188446”转换为浮点数时

(float)double_variable

我看到结果浮点变量是“91.1515”。

为什么我会丢失这么多精确度?我需要使用其他数据类型吗?

【问题讨论】:

  • 嗯,是的,如果您想要超过 7 位有效数字的精度,则需要不同的数据类型。来自the documentation:“单个值具有最多 7 位十进制数字的精度,但内部最多保留 9 位数字。” (请注意,尽管您只看到 6 位数字,那是因为该值是 91.15150 到 7 位有效数字。)从根本上说,如果您不想失去精度,请不要使用精度较低的类型。
  • 如果精度损失很关键(例如财务计算),您可以尝试使用 Decimal 类型
  • 您为什么希望它不会丢失精度?你为什么要考虑使用float - 为什么不继续使用double

标签: c# floating-point


【解决方案1】:

C# 和许多其他语言使用IEEE 754 作为其浮点数据类型的规范。浮点数表示为有效数和指数,类似于科学计数法中的十进制数表示为

1.234567890 x 10^12
     ^          ^
  mantissa   exponent

我不会详细介绍(Wikipedia 文章对此进行了详细说明),但 IEEE 754 specifies that

  • 对于 32 位浮点数,例如 C# float 数据类型,其有效位精度为 24 位,指数精度为 8 位。

  • 对于 64 位浮点数,例如 C# double 数据类型,其有效位精度为 53 位,指数精度为 11 位。

因为float只有24的精度,所以只能表示7-8位的精度。相反,double 的精度为 53 ,因此精度约为 15-16

正如 cmets 中所说,如果您不想失去精度,请不要从 double(总共 64 位)变为 float(总共 32 位)。根据您的应用程序,您也许可以使用具有 28-29 个十进制数字精度的 decimal 数据类型 - 但会受到惩罚,因为 (a) 涉及它的计算比 doublefloat 慢,并且(b) 它通常不受外部库的支持。


请注意,您所说的 91.15149709518846 实际上会被编译器解释为 91.1514970951884 - 例如,请参见 this

double value = 91.151497095188446;
Console.WriteLine(value);
// prints 91.1514970951884

【讨论】:

    【解决方案2】:

    你会在这里找到详细的解释:https://stackoverflow.com/a/2386882/10863059

    基本上,与 double(8 字节)相比,float 占用的内存空间更小(4 字节),但这只是故事的一部分。

    【讨论】:

      【解决方案3】:

      浮点类型将小数部分存储为 2 的倒数。为此,他们 只能表示精确值,例如 10、10.25、10.5 等。其他号码, 例如 1.23 或 19.99,不能精确表示,只是一个近似值。 即使 double 具有 15 位小数精度,而浮点数只有 7 位, 重复计算时精度损失开始累积。

      这使得 double 和 float 难以甚至不适合在某些类型的 应用程序,例如金融应用程序,其中精度是关键。为此, 提供十进制类型

      参考:学习 C# 编程,用 C# 语言打下坚实基础的指南 编写高效的程序 作者:Marius Bancila, 拉斐尔·里亚尔迪, Ankit Sharma

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-10-29
        • 2011-12-17
        • 1970-01-01
        • 2023-03-18
        • 2011-03-30
        • 1970-01-01
        • 2019-03-06
        相关资源
        最近更新 更多