如何计算浮点型精度,是否有意义?

Evg*_*hin 0 c# math floating-point ieee-754

我在理解浮点类型的精度时遇到问题。msdn将该精度写入6 到 9 位数字。但我注意到精度取决于数字的大小:

  float smallNumber = 1.0000001f;
  Console.WriteLine(smallNumber); // 1.0000001

  bigNumber = 100000001f;
  Console.WriteLine(bigNumber); // 100000000

Run Code Online (Sandbox Code Playgroud)

smallNumber 比 big 更精确,我了解 IEEE754,但我不明白 MSDN 如何计算精度,这是否有意义?

此外,您可以在此处使用浮点格式的数字表示。请在“您输入”输入中输入 100000000 值,然后单击右侧的“+1”。然后将输入的值更改为 1,并再次单击“+1”。您可能会看到精度上的差异。

Eri*_*hil 7

MSDN 文档是无意义的和错误的。

糟糕的概念。二进制浮点格式在十进制数字中没有任何精度,因为它根本没有十进制数字。它用一个符号、固定数量的二进制数字(位)和一个 2 的幂的指数来表示数字。

错在高端。浮点格式以无限精度精确表示许多数字。例如,“3”是精确表示的。你可以用十进制任意远写,3.0000000000...,所有的十进制数字都是正确的。另一个例子是1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125•10 ?45。这个数字有 105 位十进制有效数字,但float格式准确地表示它(它是 2 ?149)。

低端错了。当“999999.97”从十进制转换为 时float,结果为 1,000,000。因此,即使是一位十进制数字也是正确的。

不是准确性的衡量标准。由于float有效数有24位,其最低位的分辨率比最高位的分辨率高约2 23倍。从 log 10 2 23大约是 6.9 的意义上说,这大约是 6.9 位数字。但这只是告诉我们表示的分辨率——粗糙程度。当我们将数字转换为float格式时,我们得到的结果与数字最多相差这个分辨率的 ½,因为我们四舍五入到最接近的可表示值。所以转换为float2 24的相对误差最多为 1 部分,相当于上述意义上的约 7.2 位数字。如果我们用数字来衡量分辨率,那么我们说分辨率大约是 7.2 位,而不是 6-9 位。

这些数字从何而来?

那么,如果“~6-9 位数字”不是一个正确的概念,不是来自数字的实际界限,也不是测量准确度,它从何而来?我们不能确定,但​​ 6 和 9 确实出现在float格式的两种描述中。

6是保证这一点的最大数x

  • 如果任何最多x位有效数字的十进制数字在float格式的正常指数范围内并被转换为格式中表示的最接近的值,那么,当结果被转换为最多x位有效数字的最接近的十进制数字时,该转换的结果等于原始数字。

所以可以说float至少可以保留六位十进制数字。然而,正如我们将看到的,没有涉及九位数字的界限。

9 是保证这一点的最小数字x

  • 如果将任何有限float数转换为最接近的x位十进制数字,则当结果转换为 中可表示的最接近的值时float,该转换的结果等于原始数字。

打个比方,如果float是一个容器,那么保证能装进去的最大“十进制容器”是六位数,保证能装进去的最小“十进制容器”是九位数。图 6 和图 9 类似于float容器的内部和外部测量。

假设您有一个 7.2 个单位长的块,并且您正在查看它在一排每 1 个单位长的砖块上的位置。如果你把方块的起点放在一块砖的起点,它会延伸 7.2 块砖。但是,其他人会选择从哪里开始,他们可能会从砖块中间开始。然后它将覆盖那块砖的一部分,接下来的所有 6 块砖,以及最后一块砖的一部分(例如,0.5 + 6 + .7 = 7.2)。所以一个 7.2 单元的块只能保证覆盖 6 块砖。相反,如果您选择放置它们的位置,则 8 块砖可以覆盖 7.2 单元的块。但是,如果其他人选择从哪里开始,第一个可能只覆盖块的 0.1 个单位。然后你还需要 7 个和另一个分数,所以需要 9 个砖块。

这个类比成立的原因是,2 的幂和 10 的幂彼此之间的间隔是不规则的。2 10 (1024) 接近 10 3 (1000)。10 是float从 1024(含)到 2048(不含)的数字格式中使用的指数。所以这个从 1024 到 2048 的区间就像一个块,刚好在 100-1000 结束和 1000-10,000 块开始之后放置。

但请注意,这个涉及 9 位数字的属性是外部度量——它不是一种float可以执行的能力或可以提供的服务。这是float需要的东西(如果它以十进制格式保存),而不是它提供的东西。所以它不是一个float可以存储多少位数字的限制。

进一步阅读

为了更好地理解浮点运算,可以考虑学习IEEE-754 浮点运算标准或像让-米歇尔穆勒等人编写的浮点运算手册这样的好教科书。

  • @SteveSummit:是的。 (3认同)
  • 最初的问题是关于 C# 的,所以这基本上是一个题外话,但是可以肯定地说“6 是保证这一点的最大数字 *x*”就是 C 所说的“FLT_DIG”,而“9是保证这一点的最小数字*x*”,C 称之为“FLT_DECIMAL_DIG”? (2认同)