如何避免大数的科学记数法?
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.h
和cmath.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
【讨论】:
以上是关于如何避免大数的科学记数法?的主要内容,如果未能解决你的问题,请参考以下文章