浮点数的小数部分中的最大基数为10的数字是多少

时间:2016-10-03 15:19:14

标签: c++ floating-point max decimal numeric-limits

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

我希望标准中有一些内容,例如#definenumeric_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实际上是在浮点的分数中表示的,并且它没有被负指数向下移动。 / p>

我知道我们有min_exponent10这就是我应该为此寻找的东西吗?

5 个答案:

答案 0 :(得分: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,即

  

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

对于64位IEEE 754,您有:

最小指数-1022

分数位52

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

  

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

答案 1 :(得分:2)

我合理地确定标准没有(并且不能施加其他限制)提供预定义的常量来指定您要求的数字。

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

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

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

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

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

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

答案 2 :(得分:2)

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

0x1fffffffff: 6.79038653103946484377229843314461138310092194376426254559711066591341199697795428720719286691708030861257706156230052848270284693281999335257284225503333669621306363815173250949032599895939692485035854980886484314557513280150853794570573829826804739857524570119217960803180407426491111965307363413286730767487798931547682783285587237815896874519586247523590053014866896717670220058410681569440570831708335441818365520992706048929416204456554630166566744761505361796609796460970870848607530858252375458051540998088502646723863112078256283270166032158271317445541281132771025125941275958574416739473064262902084753576460564142184397648156338301251133401530253459935315283438205175670237273725515135411912887673125670769439486684770912461317493580281734466552734375E-313

答案 3 :(得分: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重复,但是在答案变成无意义之前你在小数点之后有十六个三分。

如果你有一个非常大的数字,比如10亿除以3(1000000000.0/3.0),那么在我的机器上答案看起来像这样:

1000000000.0/3.0 = 333333333.333333313465118

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

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

1000000000000000000.0/3.0 = 333333333333333312.000000000000000

您仍然有十六位数的精度,但这些数字的零位于小数点后面。

答案 4 :(得分: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。