C语言中FLT_DIG、DBL_DIG、LDBL_DIG是如何确定的
How are FLT_DIG, DBL_DIG, and LDBL_DIG determined in C
FLT_DIG、DBL_DIG、LDBL_DIG分别是float、double、long double类型可以准确表示的小数位数。
#include <stdio.h>
#include <float.h>
int main(void)
{
printf("%d, %d, %d\n", FLT_DIG, DBL_DIG, LDBL_DIG);
return 0;
}
打印 6
、15
和 18
。该标准在第 5.2.4.2.2 节中给出了准确的公式——例如对于浮点数,p = 24 和 b = 2:
但是我不清楚上面的公式("otherwise")是怎么推导出来的。有人可以解释一下吗?
以下是我的推理,没有回答问题。考虑在有效位(IEEE-754 标准)中有 23 位的浮点类型。可以准确表示的最大二进制整数为:
100...00 (25 digits total, because we have an implicit 1)
= 2^24
= 10^(24*log(2))
因此#个十进制数字:
= floor(24*log(2)) = 7
而不是标准规定的 floor(23 * log(2)) = 6
。
以下是我的看法。免责声明:我只是一个程序员,不是数学家,更不是数论家,你问的问题对他们来说形成了(我相信)一个中心定理。
每个人都知道以 10 为底数:两位数字给你 102 或 100 个值,三位数字给你 103 或 1000 个值,等等
每个程序员都知道以 10 为基数:八位给你 28 或 256 个值,十六位(两个字节)给你 216 或 65536 个值等
那么问题来了,一个十进制数有多少位?
嗯,23是8,所以多了3位。而24是16,所以还不到4位。
你知道对数吧? (您询问的公式中有一个,所以我希望您至少对它们有所了解。)对数是求幂的倒数。如果102是100,那么log10100就是2。如果28是256,那么log2 256 是 8.
所以一个十进制数的二进制位数是log210,结果大约是3.322。 (看,我是对的:大于 3,小于 4。)
我们也可以走另一条路。如果216是65536,16位对应多少十进制数?很明显是5左右:我们需要5个数字来写65536。但实际上它必须比5少一点,因为用5个十进制数字我们最多可以表示大约99999个不同的值,这超过了16位。
事实上,根据我们之前的结果,十进制数字中有 3.322 个二进制位,我们需要 16 ÷ 3.322 ≊ 4.8 位十进制数字来准确表示 16 位。
最后,让我们看看浮点数。根据维基百科,IEEE 754 single-precision floating-point format(通常是 C float
)具有 24 位的有效值(又名 "mantissa")。使用我们方便的换算系数,这相当于 24 ÷ 3.322 ≊ 7.2 十进制数字。 (实际上,由于 IEEE-754 中的复杂因素,例如非规范化数字和隐式 1 位,它比这更复杂,但现在 7.2 位数字可以作为答案。)
我有点误导你了,因为我一直在使用 log210 ≊ 的转换因子; 3.322 在二进制位和十进制数字之间来回切换,而你引用的公式有 log10 b (我们 b 大概是 2)。另外,看:它们乘以 log10 b,而我一直在除以 log210。惊喜,惊喜:log210 == 1 / (log10 2)。 (我确定有一个很好的证明,但这个答案太长了。)
How are FLT_DIG, DBL_DIG, and LDBL_DIG determined (?)
大致,用p
个二进制数,可以编码p*(log102)个十进制数。每个二进制数字都贡献了大约 .3 个十进制数字。
将浮点值和数字回忆为具有 n
表示数字和指数的十进制文本,在更大的 对数 [=53] 中呈 线性分布 =]分布.
下面的 -1 来自最坏情况下的对齐问题,其中十进制值的分布相对于二进制值最为密集。如果 float
基数为 10,则没有 -1,因为分布对齐。
The below is the reasoning I followed which does not answer the question. ...
根据 here 中的第 6 条,OP 的推理失败了。十进制值与二进制值的对齐并不总是 "work".
A float
作为 binary32 示例。
在 [233 或 8,589,934,592 ... 234 或 17,179,869,184) 范围内,再次,2 23 (8,388,608) 个值是 线性 编码的:彼此相距 1024.0。在子范围 [9,000,000,000 和 10,000,000,000) 中,大约有 976,562 个不同的值。
作为文本,范围[9,000,000*103和10,000,000*103),使用1个线索digit 和 6 trailing ones,有 1,000,000 个不同的值。根据 #1,在同一范围内,不同的 float
值少于 1,000,000 个。因此,一些十进制文本值将转换为相同的 float
。 在此范围内,我们可以使用 6 个而不是 7 个数字 进行独特的转换。
FLT_DIG、DBL_DIG、LDBL_DIG分别是float、double、long double类型可以准确表示的小数位数。
#include <stdio.h>
#include <float.h>
int main(void)
{
printf("%d, %d, %d\n", FLT_DIG, DBL_DIG, LDBL_DIG);
return 0;
}
打印 6
、15
和 18
。该标准在第 5.2.4.2.2 节中给出了准确的公式——例如对于浮点数,p = 24 和 b = 2:
但是我不清楚上面的公式("otherwise")是怎么推导出来的。有人可以解释一下吗?
以下是我的推理,没有回答问题。考虑在有效位(IEEE-754 标准)中有 23 位的浮点类型。可以准确表示的最大二进制整数为:
100...00 (25 digits total, because we have an implicit 1)
= 2^24
= 10^(24*log(2))
因此#个十进制数字:
= floor(24*log(2)) = 7
而不是标准规定的 floor(23 * log(2)) = 6
。
以下是我的看法。免责声明:我只是一个程序员,不是数学家,更不是数论家,你问的问题对他们来说形成了(我相信)一个中心定理。
每个人都知道以 10 为底数:两位数字给你 102 或 100 个值,三位数字给你 103 或 1000 个值,等等
每个程序员都知道以 10 为基数:八位给你 28 或 256 个值,十六位(两个字节)给你 216 或 65536 个值等
那么问题来了,一个十进制数有多少位?
嗯,23是8,所以多了3位。而24是16,所以还不到4位。
你知道对数吧? (您询问的公式中有一个,所以我希望您至少对它们有所了解。)对数是求幂的倒数。如果102是100,那么log10100就是2。如果28是256,那么log2 256 是 8.
所以一个十进制数的二进制位数是log210,结果大约是3.322。 (看,我是对的:大于 3,小于 4。)
我们也可以走另一条路。如果216是65536,16位对应多少十进制数?很明显是5左右:我们需要5个数字来写65536。但实际上它必须比5少一点,因为用5个十进制数字我们最多可以表示大约99999个不同的值,这超过了16位。
事实上,根据我们之前的结果,十进制数字中有 3.322 个二进制位,我们需要 16 ÷ 3.322 ≊ 4.8 位十进制数字来准确表示 16 位。
最后,让我们看看浮点数。根据维基百科,IEEE 754 single-precision floating-point format(通常是 C float
)具有 24 位的有效值(又名 "mantissa")。使用我们方便的换算系数,这相当于 24 ÷ 3.322 ≊ 7.2 十进制数字。 (实际上,由于 IEEE-754 中的复杂因素,例如非规范化数字和隐式 1 位,它比这更复杂,但现在 7.2 位数字可以作为答案。)
我有点误导你了,因为我一直在使用 log210 ≊ 的转换因子; 3.322 在二进制位和十进制数字之间来回切换,而你引用的公式有 log10 b (我们 b 大概是 2)。另外,看:它们乘以 log10 b,而我一直在除以 log210。惊喜,惊喜:log210 == 1 / (log10 2)。 (我确定有一个很好的证明,但这个答案太长了。)
How are FLT_DIG, DBL_DIG, and LDBL_DIG determined (?)
大致,用p
个二进制数,可以编码p*(log102)个十进制数。每个二进制数字都贡献了大约 .3 个十进制数字。
将浮点值和数字回忆为具有 n
表示数字和指数的十进制文本,在更大的 对数 [=53] 中呈 线性分布 =]分布.
下面的 -1 来自最坏情况下的对齐问题,其中十进制值的分布相对于二进制值最为密集。如果 float
基数为 10,则没有 -1,因为分布对齐。
The below is the reasoning I followed which does not answer the question. ...
根据 here 中的第 6 条,OP 的推理失败了。十进制值与二进制值的对齐并不总是 "work".
A float
作为 binary32 示例。
在 [233 或 8,589,934,592 ... 234 或 17,179,869,184) 范围内,再次,2 23 (8,388,608) 个值是 线性 编码的:彼此相距 1024.0。在子范围 [9,000,000,000 和 10,000,000,000) 中,大约有 976,562 个不同的值。
作为文本,范围[9,000,000*103和10,000,000*103),使用1个线索digit 和 6 trailing ones,有 1,000,000 个不同的值。根据 #1,在同一范围内,不同的
float
值少于 1,000,000 个。因此,一些十进制文本值将转换为相同的float
。 在此范围内,我们可以使用 6 个而不是 7 个数字 进行独特的转换。