4

c++ pow(2,1000) 通常对于 double 来说很大,但它正在工作。为什么?

所以我已经学习 C++ 几个星期了,但数据类型仍然让我感到困惑。

首先是一件小事:0xbadc0de 在另一个线程中发布的代码对我不起作用。首先pow(2,1000)给我this more than once instance of overloaded function "pow" matches the argument list.

我通过更改来修复它pow(2,1000)- >pow(2.0,1000) 似乎很好,我运行它并得到这个:

http://i.stack.imgur.com/bbRat.png

代替

10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376

它缺少很多值,可能是什么原因造成的?

但现在真正的问题。我想知道 302 位长数字如何适合双精度(8 字节)?0xFFFFFFFFFFFFFFFF = 18446744073709551616 那么这个数字怎么会大于这个呢?

我认为这与浮点数编码有关。如果不是 0xFFFFFFFFFFFFFFFF,那么可以存储在 8 个字节中的最大数字是多少?

4

5 回答 5

8

八个字节包含 64 位信息,因此您可以2^64 ~ 10^20使用这些位存储唯一的项目。这些项目可以很容易地解释为从0到的整数2^64 - 1。所以你不能在 8 个字节中存储 302 个十进制数字;0和之间的大多数数字10^303 - 1不能这样表示。

浮点数可以保持 302 位十进制数字的近似值;这是因为它们分别存储尾数和指数。此表示中的数字存储一定数量的有效数字(如果我没记错的话,双精度数为 15-16)和指数(可以进入数百个内存服务)。但是,如果一个小数是 X 字节长,那么它只能区分2^(8X)不同的值......不太可能精确地表示具有 302 个十进制数字的整数。

要表示这样的数字,您必须使用更多位:实际上大约 1000 或 125 个字节。

于 2013-01-28T17:07:42.483 回答
1

它被称为“浮点”是有原因的。数据类型包含标准意义上的数字和表示小数点所在位置的指数。这就是为什么pow(2.0, 1000)有效,这就是为什么你会看到很多零。浮点数(或双精度数,只是一个更大的浮点数)数包含固定位数的精度。所有剩余的数字最终都为零。尝试一下pow(2.0, -1000),你会看到相反的情况。

浮点数(32 位)中精度的小数位数约为 7,而双精度数(64 位)约为 16 位小数。

现在大多数系统都使用IEEE floating point,我只是链接到一个非常好的描述。此外,有关特定标准IEEE 754-1985的文章详细描述了各种大小的浮点数的位布局。

于 2013-01-28T17:06:24.087 回答
1

浮点类型可以覆盖比相同大小的整数类型更大的范围,但精度较低。

它们代表一个数字:

  • 一个符号位 s来表示正或负;
  • 尾数 ,介于 1 和 2 之间的m值,给出一定数量的精度;
  • 一个指数 e来表示数字的规模。

该值本身计算为m * pow(2,e),如果设置了符号位,则取反。

标准double有一个53 位尾数,它提供大约 16 位十进制数字的精度。

因此,如果您需要表示一个精度超过(例如)64 位的整数,那么 64 位整数和 64 位浮点类型都不起作用。您将需要一个大整数类型,用尽可能多的位来表示您正在使用的值,或者(取决于您要解决的问题)一些其他表示,例如素数分解。标准 C++ 中没有这种类型,因此您需要自己制作。

于 2013-01-28T17:10:48.353 回答
1

2.0 ^ 1000 在数学上将具有十进制(非浮点)输出。IEEE 浮点数,在您的情况下为双精度数(因为 pow 函数接受双精度数并输出双精度数)具有分配给尾数的 64 位表示的 52 位。如果你算一下,2^52 = 4,503,599,627,370,496。因为浮点数可以表示正数和负数,所以整数表示实际上将是 ~ 2^51 = 2,251,799,813,685,248。注意有 16 位数字。您看到的输出中有 16 个质量(非零)数字。

本质上 pow 函数将执行取幂,但是一旦取幂超过 ~2^51,它将开始失去精度。最终它将保持前 16 位小数的精度,但所有其他正确的数字将不受保证。

因此这是一个浮点精度/舍入问题。

如果您严格处于无符号整数域中,则该数字将在 (2^64 - 1) = 18,446,744,073,709,551,616 之后溢出。溢出的意思是,您实际上永远不会看到数字比提供的数字高,事实上我相信这个操作的答案是 0。一旦答案超出 2^64,结果寄存器将为零,任何乘法后缀将为 0 * 2,这将始终导致 0。我必须尝试一下。

可以使用使用多精度库的标准计算机获得确切的答案(如您所示)。它们的作用是通过连接多个较小的数据类型来模拟更大的位计算机,并使用算法动态转换和打印。Mathematica 是实现任意精度数学计算库的数学引擎的一个示例。

于 2013-01-28T17:17:39.793 回答
1

如果要计算某些字节可以容纳的数字范围,应该是(2^(64bits - 1bit)) 到(2^(64bits - 1bit) - 1)。

因为变量的最左边的数字用于表示符号(+ 和 -)。所以数字的负数范围应该是:(2^(64bits - 1bit)),数字正数的范围应该是:(2^(64bits - 1bit) - 1) 有-1由于 0 的正范围(避免每边都计为 0 的声誉)。

例如,如果我们计算 64 位,范围应该是 ==> 大约 [-9.223372e+18] 到 [9.223372e+18]

于 2013-08-23T22:07:53.413 回答