【发布时间】:2012-03-19 06:09:30
【问题描述】:
通常我们说浮点数的精度为小数点后 6 位。但是如果我们存储大量 10^30 的顺序,我们将不会得到小数点后 6 位。那么说浮点数精度为小数点后6位是否正确?
【问题讨论】:
-
Significant Figures 将是更准确的术语。
标签: c floating-point precision
通常我们说浮点数的精度为小数点后 6 位。但是如果我们存储大量 10^30 的顺序,我们将不会得到小数点后 6 位。那么说浮点数精度为小数点后6位是否正确?
【问题讨论】:
标签: c floating-point precision
“小数点后6位”是废话,你的例子很好地证明了这一点。
This 是 float 数据类型的精确规范。
float 的精度为 24 位。根据在线资料,有 23 位表示二进制点之后的分数,此外还有一个“隐式前导位”。这总共给出了 24 个有效位。
因此在十进制数字中,这大约是:
24 * log(2) / log(10) = 7.22
【讨论】:
听起来您是在询问decimal places(小数点后的数字)的精度,而significant figures(不包括前导零和尾随零的总位数)是描述数字准确性的更好方法。
您是正确的,小数点后的位数会随着数字变大而改变 - 但如果我们说的是精度,那么当数字变大时,有效数字的位数不会改变。然而,十进制数的答案并不简单:
如今,大多数系统都使用IEE floating point format 来表示 C 中的数字。但是,如果您遇到不寻常的事情,则值得检查一下。单精度 IEE float 数字由三部分组成:
正如我们所料,这一切都以二进制形式存储。
如果您使用的是 IEE-754 数字,“有多少有效数字”可能不是一个容易考虑的方法,因为精度是用二进制有效数字而不是十进制来衡量的。 floats 的小数部分只有 23 位精度,但是因为有一个隐含的前导位(除非小数部分全为零,表示最终值为 1),所以有 24 位有效精度。
这意味着有 24 个有效的二进制数字,它不能转换为十进制有效数字的确切数量。您可以使用公式 24 * log(2) / log(10) 来确定有 7.225 位十进制精度,这不是您问题的一个很好的答案,因为有 24 个有效二进制数字有 6 位有效小数位。
因此,单精度浮点数具有6-9 位精度的有效十进制数字,具体取决于数字。
有趣的是,您还可以使用此精度计算出可以成功表示为单精度浮点数的最大连续整数(从零开始计数)。它是 2^24 或 16,777,216。您可以精确存储更大的整数,但前提是它们可以用 24 位有效二进制数字表示。
更多琐事:分数组件的有限大小与 Javascript 中导致此问题的原因相同:
> console.log(9999999999999999);
10000000000000000
Javascript 数字始终表示为双精度浮点数,其精度为 53 位。这意味着在 2^53 和 2^54 之间,只能表示偶数,因为任何奇数的最后一位都会丢失。
【讨论】:
浮点数的精度应该以二进制数字而不是十进制数字来衡量。这是因为计算机对二进制数进行运算,而二进制小数只能近似小数。
语言律师会说 float 的确切宽度未由 C 标准指定,因此取决于实现,但在任何平台上,您都可能遇到 C float 表示 IEEE754 single-precision号码。
IEEE754 指定浮点数在scientific notation 中:(-1)s×2e×m
其中 s 为 1 位宽,e 为 8 位宽,m 为 23 位宽。在数学上,m 是 24 位宽,因为它总是假设最高位是 1。
因此,可以用这种表示近似的十进制数字的最大数量是:log10(224) = 7.22。 这近似于七位有效十进制数字,以及从 2-126 到 2127 的指数。
请注意,指数是单独测量的。这就像你使用普通的scientific notation,比如“一个人重 72.3 公斤 = 7.23×104 克”。注意这里有三个有效数字,表示这个数字只精确到100克以内。但也有一个完全不同的数字 exponent。你可以有一个非常大的指数,有效数字很少,比如“太阳重 1.99×1033 克”。大数字,几位数。
【讨论】:
简而言之,一个浮点数可以存储大约 7-8 个有效的十进制数字。让我用一个例子来说明这一点:
1234567001.00
^
+---------------- this information is lost
.01234567001
^
+-------------- this information is lost
基本上,浮点数存储两个值:1234567 和小数点的位置。
现在,这是一个简化的示例。浮点数存储 二进制 值而不是十进制值。 32-bit IEEE 754 float 有 23 个“有效位”(加上始终假定为 1 的第一个)的空间,对应于大约 7-8 个十进制数字。
1234567001.00 (dec) =
1001001100101011111111101011001.00 (bin) gets rounded to
1001001100101011111111110000000.00 =
| 23 bits |
1234567040.00 (dec)
这正是 C 产生的:
void main() {
float a = 1234567001;
printf("%f", a); // outputs 1234567040
}
【讨论】: