8个字节如何保存302个十进制数字? (欧拉挑战16)

时间:2013-01-28 16:58:07

标签: c++ types integer double

c++ pow(2,1000) is normaly to big for double, but it's working. why?

所以我几周学习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个字节中的是什么?

5 个答案:

答案 0 :(得分:8)

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

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

要表示此类数字,您必须使用更多位:大约1000,实际或125字节。

答案 1 :(得分:1)

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

float(32位)中精度的十进制数字大约是7,而对于double(64位),它大约是16位十进制数。

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

答案 2 :(得分:1)

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

它们代表一个数字:

  • 符号位 s表示正面或负面;
  • a 尾数 m,介于1和2之间的值,给出一定数量的精度;
  • exponent e表示该数字的比例。

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

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

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

答案 3 :(得分:1)

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

本质上,pow函数将执行取幂,但一旦取幂超过〜^ ^ 51,它将开始失去精度。最终它将保持精确的前16位十进制数字,但所有其他数字右边将无法保证。

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

如果您严格使用无符号整数域,则在(2 ^ 64 - 1)= 18,446,744,073,709,551,616之后该数字将溢出。溢出的意思是,你永远不会真正看到数字比提供的数字更高,事实上我相信这个操作的答案是0。一旦答案超过2 ^ 64,结果寄存器将为零,并且任何乘法后缀将为0 * 2,这将总是导致0.我将不得不尝试它。

使用多精度图书馆的标准计算机可以获得确切的答案(如图所示)。这些操作是通过连接多个较小的数据类型来模拟更大的计算机,并使用算法进行转换和即时打印。 Mathematica是实现任意精度数学计算库的数学引擎的一个示例。

答案 4 :(得分:0)

如果你想计算一些字节可以保持的数字范围,它应该是(2 ^(64bits - 1bit))到(2 ^(64bits - 1bit) - 1)。

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

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