如何避免大数使用科学计数法?

27

我正在计算2^1000,得到的结果是:

1.07151e+301

请问有没有办法将这个结果转换成一个不带e+301的真实数字?或者,有没有人可以告诉我如何通过处理e+301部分来将其转换为实际数字?


这可能来自这里吗?http://projecteuler.net/index.php?section=problems&id=16 - Tom Ritter
1
在二进制中很简单 - 一个1后面跟着1000个零。创建一个简单的算法来进行长除法,你就可以解决问题了(反复除以1010并求余数之和)。 - Skizz
2
这是一个合适的数字。 - Lightness Races in Orbit
9个回答

16

所以,我认为你真正想要的只是在不使用科学计数法的情况下打印它。如果你正在使用printf,你想要的是:

printf( "%f1000.0", value );
// note that 1000 is way larger than need be,
// I'm just too lazy to count the digits

使用 cout 时,可以尝试以下方式:

cout.setf(ios::fixed);
cout << setprecision(0) << value;

如果你想将其打印为2的幂(2^1000 vs 10715...),那么你需要自行处理。


有没有办法将输出放在一个字符串中而不是打印在屏幕上? - AntonioCS
1
只需使用snprintf。请注意,由于这个数字仅是2的幂次方,您不会丢失任何信息,但如果您尝试使用3^1000进行相同的操作,double将无法存储所需的所有精度。 - Eclipse
或者如果你正在使用C++的流技术,可以使用std::ostringstream实例来替代cout。 - Fred Larson
@tvanfosson 我也有类似的问题在这里。如果可能的话,你能帮我解决吗? - user1950349

13

机器寄存器直接操作的数字大小存在实际限制。如果使用双精度浮点数,则总共有64个位,其中一些用于尾数,一些用于指数,1个用于符号位。

要表示2 ^ 1000而不失精度,需要使用1001位整数。为了使用这样的数字,您需要使用具有大数支持的库,例如 GNU MP


1
其实是1001位 :) 2^1 需要2位;然后通过归纳得出。 - Jonathan Leffler
你说得对,感谢指出,我已经编辑过来反映了。 - Louis Gerbarg
结尾似乎从第一句话中被切断了:“有一个基本限制,即可以表示的数字有多大”实际上应该是“在机器寄存器中,可以表示的数字有一个实际限制。” - florin

10

你需要使用专门设计用于长数字的数值类。

如果要精确表示2的1000次方,则根据定义,您需要一个实际上保存1001个二进制位的数字格式。最长的常规原始整数格式通常只有64位。

顺便说一句,答案是:

% perl -Mbigint -e 'print 2**1000'
10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376

1
如果你试图从Mbigint中取出perl,幽灵会打败你并把它还给他们。抢劫矮人部落是不好的行为,除非你是印第安纳·琼斯。 - Peter Wone
我假设你已经知道了,但这是一个欧拉计划的问题。有些人可能认为明确地拼出大部分解决方案有点不雅。 - Beska

4
如果你想在C++中自己完成,可以创建一个数字数组并自行进行计算。以下是经过测试和验证的示例:
unsigned int result[400]; // result digits
unsigned int i, j, carry;

// Initialize result digits
for (i = 0; i < 399; i++) {
  result[i] = 0;
}
result[399] = 2;

for (i = 2; i <= 1000; i++) { // Calculate 2^i
  carry = 0;
  for (j = 399; j > 0; j--) {
    result[j] <<= 1;    // multiply with 2
    result[j] += carry; // add carry
    carry = result[j] / 10;
    result[j] %= 10;    // we want one digit (0-9) only
  }
}

printf("2 ^ 1000 = ");
// print result digits
for (i = 0; i < 400; i++) {
  if (result[i] != 0) { // no leading zeros, please
    for (j = i; j < 400; j++) {
      printf("%d", result[j]);
    }
    break;
  }
}
printf("\n");

2

cout << fixed << your_number;

但它可能不会显示整个数字。正如之前有人说的那样,您需要编写一个类。


2

如果您的应用逻辑允许,一种选择是更改您操作的单位...

如果你用埃为单位测量从纽约到巴黎的距离,选择英里或千米。除了纯数学需求(比如说加密学中分解质数或...研究黎曼猜想),很少需要保留那么多位精度。

另一方面,如果您正在进行需要完全准确的整数值的操作,那么您可能需要获取专门设计用于处理大数的软件...这样的软件绝对可用,但我不熟悉该领域(成本、供应商、能力等)。如果成本是问题,并且您正在考虑编写自己的软件,我不太清楚其中涉及的内容是否值得努力...


0

需要包含头文件 limits.hcmath.h

cout.precision(0);
cout<< fixed<< pow(2,31);               //OR ANY NUMBER HERE

使用cout.precision来设置精度。

0
你正在获取变量类型所支持的尽可能精确的数字。那个数字大约是1后面跟着301个零。要获得精确的数字,你需要使用支持大数的库,或者使用专门用于这类数学运算的语言(如maple、matlab等)。

0

我曾经遇到过同样的问题。我试图直接打印2^34,但输出结果是3.43597e+010

你应该考虑将其存储在变量中,这解决了我的问题。例如:

long long int a= pow(2,34)-2;
cout<<a;

输出结果是一个实数,正如我所期望的 - 34359738366


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接