浮点数的小数部分最多有多少位 10 位数字

What Are the Maximum Number of Base-10 Digits in the Fractional Part of a Floating Point Number

如果可以输出一个浮点数,这样就没有值的截断(比如setpercision)并且数字以固定表示法输出(比如fixed)是什么保证浮点数的整个小数部分可以存储在缓冲区中所需的缓冲区大小?

我希望标准中有一些东西,比如 #definenumeric_limits 中的东西可以告诉我浮点小数部分的以 10 为底的最大值位置类型。

我在这里询问了浮点类型的小数部分中以 10 为基数的最大位数:

但我意识到这可能更复杂。例如,1.0 / 3.0 是一个无限重复的数字序列。当我使用 fixed 格式输出时,我在重复 0 之前得到了很多地方:

0.333333333333333314829616256247390992939472198486328125

但我不一定能说这是最大精度,因为我不知道浮点小数中实际表示了多少尾随 0,而且它没有被负指数向下移动.

我知道我们有 min_exponent10 是我应该寻找的吗?

std::numeric_limits<double>::min_exponent

Minimum negative integer value such that radix raised to (min_exponent-1) generates a normalized floating-point number. Equivalent to FLT_MIN_EXP, DBL_MIN_EXP or LDBL_MIN_EXP for floating types.

min_exponent10 也可用。

Minimum negative integer value such that 10 raised to that power generates a normalized floating-point number. Equivalent to FLT_MIN_10_EXP, DBL_MIN_10_EXP or LDBL_MIN_10_EXP for floating types.

您并不是真的想知道有多少 "digits are in the fractional part",此声明表明您并不是 100% 清楚浮点表示法背后发生的事情。整数和小数部分没有单独的精度。

您真正想知道的是表示的精度

1) 一个 32 位的单精度 IEEE754 数字有 24 个尾数位,这给出了大约 24 * log10(2) = 7.2 位数的精度。

2) 一个 64 位双精度 IEEE754 数字有 53 个尾数位,这给出了大约 53 * log10(2) = 16.0 位数的精度。

假设您正在使用双精度数字。如果你有一个非常小的以 10 为底的数字,比如介于 0 和 1 之间,那么你将在小数点后有大约 16 位小数精度。这就是上面显示的 1.0/3.0 示例 - 您知道答案应该是 0.3 重复,但是在答案变成废话之前小数点后有 16 个三。

如果你有一个非常大的数字,比如十亿除以三 (1000000000.0/3.0) 那么在我的机器上答案将如下所示:

1000000000.0/3.0 = 333333333.333333313465118

在这种情况下,您仍然有大约 16 位 精度,但精度分为整数部分和小数部分。整数部分有9位精确数字,小数部分有7位精确数字。小数部分以后的八位都是垃圾

同样,假设我们将一五分之一(18 个零)除以三。在我的机器上:

1000000000000000000.0/3.0 = 333333333333333312.000000000000000

您仍有 16 位精度,但这些数字中有 0 位在小数点后。

我有理由相信标准不会(并且不能,在不施加其他限制的情况下)提供预定义常量来指定您要求的数字。

浮点数最常以 2 进制表示,但 16 进制和 10 进制也得到相当广泛的使用。

在所有这些情况下,基数中的唯一因数(2 和可能的 5)也是 10 的因数。因此,在将它们转换为基数 10(十进制)时,我们永远不会得到无限重复的数字.

不过,标准并未将浮点数限制为此类表示形式。理论上,如果有人真的想要他们可以使用(例如)base 3 或 base 7 作为他们的浮点表示。如果他们这样做了,那么存储一个在转换为十进制时会无限重复的数字将是微不足道的。比如0.1以3为底表示1/3,转换为10为底会无限重复。虽然我没听说过有人这样做,但我相信这样的实现可以满足标准的要求。

对于典型的二进制表示,min_exponent 可能是您想要的值的合理代理。不幸的是,可能无法比这更准确地说明事情了。

例如,一个实现被允许以比它存储在内存中更高的精度存储中间值,因此(例如)如果您在源代码中按字面意思给出 1.0/3.0,结果可能实际上不同于在 运行 时间读取一对输入,输入 1 和 3,然后除以它们所产生的值。在前一种情况下,除法可能在编译时进行,所以你打印出来的结果正好是double的大小,没有多余的。当你在运行时输入两个值,除法会在运行时进行,你可能会得到更高精度的结果。

该标准还要求将浮点数的基数记录为 std::numeric_limits<T>::radix。基于此,你可以根据基数min_exponent计算小数点后最大位数的近似值,只要基数的质因数与10 的质因数。

如果考虑 32 位和 64 位 IEEE 754 数字,可以按如下所述计算。

都是关于 2 的负幂。让我们看看每个指数的贡献:

2^-1 = 0.5         i.e. 1 digit
2^-2 = 0.25        i.e. 2 digits
2^-3 = 0.125       i.e. 3 digits
2^-4 = 0.0625      i.e. 4 digits
....
2^-N = 0.0000..    i.e. N digits

因为10进制数总是以5结尾,你可以看到当指数减1时,10进制数增加1。所以2^(-N)将需要N个数字

另请注意,在添加这些贡献时,结果位数由最小的数字决定。所以你需要找出的是可以贡献的最小指数。

对于 32 位 IEEE 754,您有:

最小指数-126

分数位 23

所以最小的指数是-126 + -23 = -149,所以最小的贡献将来自2^-149,即

For 32 bit IEEE 754 printed in base-10 there can be 149 fractional digits

对于 64 位 IEEE 754,您有:

最小指数-1022

分数位 52

所以最小的指数是-1022 + -52 = -1074,所以最小的贡献将来自2^-1074,即

For 64 bit IEEE 754 printed in base-10 there can be 1074 fractional digits

对于 64 位 IEEE 双精度,精确十进制转换中的最大有效数字位数是 767。这是具有最小指数值 (1) 和最多小数位集的值的精确十进制表示(53)。 (最大的次正规值具有相同的有效小数位数。)

0x1fffffffff: 6.79038653103946484377229843314461138310092194376426254559711066591341199697795428720719286691708030861257706156230052848270284693281999335257284225503333669621306363815173250949032599895939692485035854980886484314557513280150853794570573829826804739857524570119217960803180407426491111965307363413286730767487798931547682783285587237815896874519586247523590053014866896717670220058410681569440570831708335441818365520992706048929416204456554630166566744761505361796609796460970870848607530858252375458051540998088502646723863112078256283270166032158271317445541281132771025125941275958574416739473064262902084753576460564142184397648156338301251133401530253459935315283438205175670237273725515135411912887673125670769439486684770912461317493580281734466552734375E-313