如何避免大数的科学记数法?

Posted

技术标签:

【中文标题】如何避免大数的科学记数法?【英文标题】:How do I avoid scientific notation for large numbers? 【发布时间】:2008-11-05 14:23:32 【问题描述】:

我正在做 2^1000,我得到了这个:

1.07151e+301

有没有办法在没有 e+301 的情况下将其实际转换为正确的数字,或者至少有人可以告诉我在哪里可以看到如何通过某种方式使用 e+ 将其转换为实数301部分?

【问题讨论】:

这可能来自这里吗? projecteuler.net/index.php?section=problems&id=16 二进制很简单 - 一个 1 后跟 1000 个零。创建一个简单的算法来进行长除法,然后你就被排序了(反复除以 1010 并对余数求和)。 一个正确的数字。 【参考方案1】:

所以,我认为您真正想要的只是能够在没有科学记数法的情况下打印它。如果你使用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 对 10715...),您只能靠自己了。

【讨论】:

有什么办法可以将输出放在字符串中而不是打印在屏幕上?? 只需使用 snprintf。请注意,由于这个数字只是 2 的幂,因此您不会丢失任何信息,但是如果您尝试使用 3^1000 进行相同的操作,则双精度数将无法存储所有需要的精度。 或者,如果您使用 C++ 流技术,请使用 std::ostringstream 实例而不是 cout。 @tvanfosson 我也有类似的问题here。如果可以的话,你能帮帮我吗?【参考方案2】:

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

2^1000 需要一个 1001 位的整数来表示而不会丢失精度。为了处理这样的数字,您需要使用支持大数字的库,例如 GNU MP。

【讨论】:

1001 位,实际上 :) 2^1 需要 2 位;并从那里感应。 你是对的,谢谢指出,我编辑反映了这一点。 结尾似乎从第一句话中截断:“There is a basic limit to how large of a number”实际上应该说“There is a practical限制机器寄存器中可以表示的数字的大小。”【参考方案3】:

您需要使用专门为长数字设计的数字类。

要将 2^1000 表示为一个精确的数字,那么根据定义,您需要一个实际包含 1001 个二进制位的数字格式。最长的普通原始整数格式通常只有 64 位。

顺便说一句,答案是:

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

【讨论】:

如果你试图从 Mbigint 拿走 perl,Phantom 会打败你并把它还给他们。抢劫侏儒部落可不好。除非你是印第安纳琼斯。 我假设您知道这一点,但这是一个 Project Euler 问题。有些人可能会认为明确说明大部分解决方案有点令人反感。【参考方案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");

【讨论】:

【参考方案5】:

cout

但它可能不会显示整数。就像之前有人说的,你需要写一个类。

【讨论】:

【参考方案6】:

如果您的应用程序逻辑允许,一个选择是更改您正在操作的单位....

如果您以埃为单位测量从纽约到巴黎的距离,请选择英里或公里。... 除了纯粹的数学要求(比如密码学中的素数分解或……对 Reimann 假设的研究),很少需要保留这么多位数的准确性。

另一方面,如果您正在做的事情需要具有如此多数字的完全准确的整数值,那么您可能应该使用专门设计用于处理大数字的软件......这样的软件肯定是可用的,虽然我不是熟悉那个地区。 (成本、供应商、能力等) 如果成本是一个问题,并且您正在考虑自己编写,那么我对所涉及的内容知之甚少,无法知道这种方法是否值得努力……

【讨论】:

【参考方案7】:

您得到的数字与变量类型所能支持的一样精确。该数字大约是 1,后跟 301 个零。要获得精确的数字,您必须使用支持大数字的库,或者使用为这种数学(maple、matlab 等)设计的语言

【讨论】:

【参考方案8】:

包括标题limits.hcmath.h

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

使用 cout.precision 设置精度。

【讨论】:

【参考方案9】:

我遇到了同样的问题。我试图直接打印2^34,输出是 3.43597e+010.

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

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

输出是一个实数,正如我想要的那样 - 34359738366

【讨论】:

以上是关于如何避免大数的科学记数法?的主要内容,如果未能解决你的问题,请参考以下文章

如何将一串大数转换为整数?

如何在python大数计算中抑制科学计数法

scala 如何显示 大数

如何在 C/C++ 中获得大数的精确二进制表示?

如何避免mysql的double自动转为科学计数法表示

excel中如何避免科学记数法转换