在浮点数值类型的 C# 参考中,可以读到:
float
的精度为 6 到 9 位double
的精度为 15 到 17 位decimal
的精度为 28 到 29 位
在这种情况下,precision
意味着什么,特别是,precision
如何成为一个范围?由于指数和尾数的位数是固定的,precision
如何可变(在描述的范围内)?有人可以举个例子,例如precision
为 6 的float
和precision
为 9 的?
浮点数和双精度
(我会解释float
,那是IEEE-754单精度浮点格式,但double
,即IEEE-754双精度浮点格式是相同的,但数字更大。
一般来说,你可以想象一个float
是:
尾数₂ * (2 ^ 指数₂)
其中尾数₂ 表示底数二中的尾数,指数₂ 表示以二为底的指数
尾数₂ 为 23 位,指数₂ 8 位。符号还有一个额外的位,指数₂具有特殊范围的特殊格式,我们将在下面看到
还有另一个技巧:浮点通常以"规范化"形式保存:
1₂ 尾数₂ * (2 ^ 指数₂)
所以第一个数字总是 1₂,所以尾数有一个1₂ 加上 23 个二进制数字,所以完整的尾数总共有 24 位数字。
现在,对于 24 位,您可以拥有介于 0 和 16,777,216 之间的数字,即 7 个完整数字加上第 8 位"部分"数字(例如,您不能有 26,777,216)。事实上 log₁₀ 2^24 = 7.22471989594
指数"移动"一个浮点小数点,以便您可以拥有例如
1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1�我数了数)
或
1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂。 1₂1₂
或
1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂0₂
或
1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂1₂0₂0₂
等等。
指数₂有三个范围:[-1;-127]
、[1;127]
、0
非规范化数和255
NaN 和无限(其中255
表示指数的所有位都在1
)
在[-1;-127]
范围内,小数点向左移动,步数等于范围,在范围 [1;127]'小数点以同样的方式向右移动。
如果指数0
,则数是"非规范化"的。它们是丑陋的浮点数,具有特殊处理,因此速度较慢。当数字被"非规范化"时,数字的开头没有隐式的 1₂,所以你只有 23 位尾数,即 6 位精度(log₁₀ 2^23 = 6.9236899)
无法解释 9 位精度是如何产生的。
十进制
使用decimal
很容易:格式为:
尾数₂/(10 ^ 指数₂)
其中尾数₂是96位,指数₂是5位(少一点,范围是[0;28]
),再加上一个符号位,还有许多未使用的位。确切的格式写在参考源中。在decimal
s 中没有隐式的初始 1₂,所以它是纯 96 位,log₁₀ 2^96 = 28.8988795837,所以是 28 或 29 位。
浮点数/双精度/十进制中的精确数字是什么意思?
在文本和类型之间往返所需的十进制数字。
text-FP-text:当一个数字是十进制文本,然后转换为浮点类型,然后转换回具有相同位数的文本并获得相同的值时,在 FP 类型的整个指数范围内,文本版本中最大有效十进制数字的数量是较小的数字,例如 6 表示float
。 只要文本版本只显示 6 位数字,float
就可以编码一个足够接近的值。
FP-text-FP:当 FP 数字转换为十进制文本,然后转换回 FP 并获得相同的 FP 值时,文本版本所需的有效十进制数字数是较高的数字,例如 9 表示float
。 只要文本版本报告9+有效数字,就可以准确恢复原始FP值。
float
有 24 位二进制进动。 要将其转换为十进制,上述上下文很重要。 最小的非零double
大约需要 330+十进制数字才能准确地打印出来,但这很少被认为是该数字的进动。
有人可以举一个例子,例如精度为 6 的浮点数和精度为 9 的浮点数吗?
6个十进制数字总是有效的...."9999979e3"和"9999978e3"都转换为 9.999978e+09,因此往返需要 9 位有效文本数字。