5

如果可以输出一个浮点数,从而没有截断值(比如setpercisionfixed浮点数可以存储在缓冲区中吗?

我希望标准中有一些东西,比如 a#define或其他东西,numeric_limits它会告诉我浮点类型小数部分的最大基数为 10 值的位置。

我在这里询问了浮点类型小数部分中基数为 10 位的最大位数:What are the Maximum Number of Base-10 Digits in the Integral Part of a Floating Point Number

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

0.333333333333333314829616256247390992939472198486328125

但我不一定说这是最大精度,因为我不知道有多少尾随的 0 实际上表示在浮点的分数中,并且它没有被负指数向下移动。

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

4

5 回答 5

6

如果考虑 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,即

对于以 base-10 打印的 32 位 IEEE 754,可以有 149 个小数位

对于 64 位 IEEE 754,您有:

最小指数 -1022

分数位 52

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

对于以 base-10 打印的 64 位 IEEE 754,可以有 1074 个小数位

于 2016-10-03T19:11:17.543 回答
2

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

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

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

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

对于典型的二进制表示,min_exponent可能应该是您想要的值的合理代理。不幸的是,可能不可能比这更准确地陈述事情。

例如,允许实现以比存储在内存中更高的精度存储中间值,因此(例如)如果您1.0/3.0在源代码中逐字给出,结果实际上可能与读取一对产生的值不同运行时的输入,输入 1 和 3,然后将它们分开。在前一种情况下,除法可能在编译时进行,因此您打印的结果将完全是 a 的大小double,没有额外的。当您在运行时输入这两个值时,将在运行时进行除法,您可能会得到精度更高的结果。

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

于 2016-10-03T17:07:56.763 回答
2

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

0x1fffffffff: 6.79038653103946484377229843314461138310092194376426254559711066591341199697795428720719286691708030861257706156230052848270284693281999335257284225503333669621306363815173250949032599895939692485035854980886484314557513280150853794570573829826804739857524570119217960803180407426491111965307363413286730767487798931547682783285587237815896874519586247523590053014866896717670220058410681569440570831708335441818365520992706048929416204456554630166566744761505361796609796460970870848607530858252375458051540998088502646723863112078256283270166032158271317445541281132771025125941275958574416739473064262902084753576460564142184397648156338301251133401530253459935315283438205175670237273725515135411912887673125670769439486684770912461317493580281734466552734375E-313

于 2020-09-28T17:55:34.677 回答
1

您并不真的想知道“小数部分中有多少位”,此语句表明您并非 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 重复,但是在答案变成废话之前,小数点后还有十六个三。

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

1000000000.0/3.0 = 333333333.333333313465118

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

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

1000000000000000000.0/3.0 = 333333333333333312.000000000000000

您仍然有 16 位精度,但其中零位在小数点后。

于 2016-10-03T15:49:38.000 回答
0

std::numeric_limits<double>::min_exponent

最小负整数值,使得基数增加到 (min_exponent-1) 生成标准化浮点数。等效于浮点类型的 FLT_MIN_EXP、DBL_MIN_EXP 或 LDBL_MIN_EXP。

min_exponent10也可用。

最小负整数值,例如 10 的该次幂生成标准化浮点数。等效于浮点类型的 FLT_MIN_10_EXP、DBL_MIN_10_EXP 或 LDBL_MIN_10_EXP。

于 2016-10-03T15:29:53.443 回答