c++中带字符串的大数字的阶乘
factorial of big numbers with strings in c++
我正在用字符串执行阶乘程序,因为我需要大于250 的数字的阶乘
我的意图是:
string factorial(int n){
string fact="1";
for(int i=2; i<=n; i++){
b=atoi(fact)*n;
}
}
但问题是atoi不起作用。如何将字符串转换为整数。
最重要的是,我想知道这种方式的程序是否能以400的阶乘工作吗?
不确定为什么要使用字符串。可能是为了通过不使用整数向量来节省一些空间?这是我使用整数向量存储阶乘和打印的解决方案。适用于400或任何大的数字!
//Factorial of a big number
#include<iostream>
#include<vector>
using namespace std;
int main(){
int num;
cout<<"Enter the number :";
cin>>num;
vector<int> res;
res.push_back(1);
int carry=0;
for(int i=2;i<=num;i++){
for(int j=0;j<res.size();j++){
int tmp=res[j]*i;
res[j]=(tmp+carry)%10 ;
carry=(tmp+carry)/10;
}
while(carry!=0){
res.push_back(carry%10);
carry=carry/10;
}
}
for(int i=res.size()-1;i>=0;i--) cout<<res[i];
cout<<endl;
return 0;
}
输入数字:400400的因数:6403452284662389562347970319503005850702583026002959458684445942802397166831436278478647463264676294350575035856810848162883517435228961988646802997937341654150838162426461942352307046244325015114448670890662773914918117331955996440709496713452904770203224349112107975932807951015453726672516278778900093497637657103263503315653498683868313393520243737881577867915068587021827016981974006298302530859129834612622723045583395207596115053022360868104332972551948526743223243866994842243259980555161063594237696139923191340638589956537970147827206606320217379472010321356624613809077942304597360699567595836096158715123822286579549361617654480453222782581840084843641559122945427538480355837451822675900061399560145595206127211192105032491008000000000000000000000000000000000000000000000000000000000000000000000000000000000
有一个网站可以为您计算阶乘:http://www.nitrxgen.net/factorialcalc.php.报告:
得到的阶乘为250!长493位。结果还包含62个尾随零(占总数的12.58%)
323285626090910773323208145520243684709484371767378066674794242711282374755511120948881791537102819945092850735318943273093171280899082279103027907128192167652724018926473321804118626100683292536513367893908956993571353017504051317876007772479330654023390061648255522488194365725860573992226641254832982074849137721776650641276858080715312897877767295191399084437747870258917297325515028324178732065818848206478582659808848825554880000000000000000000000000000000000000000000000000000000000000000
许多使用C++CCD_ 1的系统只能工作到1E+308或大约1E+308;250的值!太大了,无法以这样的数量存储。
因此,您需要使用某种多精度算术库,或者是您自己使用C++string
值进行设计,或者使用其他广泛使用的多精度库(例如GNU GMP)。
下面的代码使用unsigned double long
来计算非常大的数字。
#include<iostream.h>
int main()
{
long k=1;
while(k!=0)
{
cout<<"nLarge Factorial Calculatornn";
cout<<"Enter a number be calculated:";
cin>>k;
if (k<=33)
{
unsigned double long fact=1;
fact=1;
for(int b=k;b>=1;b--)
{
fact=fact*b;
}
cout<<"nThe factorial of "<<k<<" is "<<fact<<"n";
}
else
{
int numArr[10000];
int total,rem=0,count;
register int i;
//int i;
for(i=0;i<10000;i++)
numArr[i]=0;
numArr[10000]=1;
for(count=2;count<=k;count++)
{
while(i>0)
{
total=numArr[i]*count+rem;
rem=0;
if(total>9)
{
numArr[i]=total%10;
rem=total/10;
}
else
{
numArr[i]=total;
}
i--;
}
rem=0;
total=0;
i=10000;
}
cout<<"The factorial of "<<k<<" is nn";
for(i=0;i<10000;i++)
{
if(numArr[i]!=0 || count==1)
{
cout<<numArr[i];
count=1;
}
}
cout<<endl;
}
cout<<"nn";
}//while
return 0;
}
输出:
![Large Factorial Calculator
Enter a number be calculated:250
The factorial of 250 is
32328562609091077323208145520243684709948437176737806667479424271128237475551112
09488817915371028199450928507353189432926730931712808990822791030279071281921676
52724018926473321804118626100683292536513367893908956993571353017504051317876007
72479330654023390061648255522488194365725860573992226412548329822048491377217766
50641276858807153128978777672951913990844377478702589172973255150283241787320658
18848206247858265980884882554880000000000000000000000000000000000000000000000000
000000000000][1]
您可以通过添加c_str()来编译atoi,但要获得阶乘还有很长的路要走。目前你身边没有b。如果你有,你仍然可以将int乘以int。所以即使你最终在返回之前将其转换为字符串,你的范围仍然是有限的。在您开始实际使用ASCII进行乘法运算或使用bignum库之前,没有必要使用字符串。
您的阶乘取决于到int的转换,它会很快溢出,所以您希望能够以这种方式计算大阶乘。为了正确地在大数字上实现计算,你需要像在纸上实现计算一样实现逻辑,这是你在小学时很难理解的规则,但将长整型整数视为"原子",而不是单个数字。不要在字符串上这样做,它会非常慢,而且充满了讨厌的转换
atoi
的方法,因为它只会给你一个32位的整数,无论你做什么,你都不会从中得到超过20亿(给予或索取)。即使你把数字增加一倍,你也只能达到20或21左右。
写一个字符串乘法例程并不难(相对而言),它取一个小(ish)数字,对每个数字进行乘法运算,并将结果波及到数字(从数字的后面开始,然后填充)。
这是我混淆的代码——它是故意写的,这样你就不能把它当作学校作业来交,但它似乎有效(与乔纳森·勒夫勒答案中的数字相匹配),而且(至少)可以达到20000![要有足够的记忆力]。
std::string operator*(const std::string &s, int x)
{
int l = (int)s.length();
std::string r;
r.resize(l);
std::fill(r.begin(), r.end(), '0');
int b = 0;
int e = ~b;
const int c = 10;
for(int i = l+e; i != e;)
{
int d = (s[i]-0x30) * x, p = i + b;
while (d && p > e)
{
int t = r[p] - 0x30 + (d % c);
r[p] = (t % c) + 0x30;
d = t / c + d / c;
p--;
}
while (d)
{
r = static_cast<char>((d % c) +0x30)+r;
d /= c;
b++;
}
i--;
}
return r;
}
在C++中,最大的整数类型是"long-long",它可以容纳64位内存,所以显然不能存储250!在整数类型中。使用字符串是一个聪明的想法,但你基本上对代码所做的是(我从未使用过atoi()函数,所以我不知道它是否适用于大于1个字符的字符串,但这无关紧要):
- 将字符串转换为integer(如果此代码运行良好,则该字符串会立即包含值249!)
- 乘以字符串的值
所以,在完成乘法运算后,您甚至不会将整数转换回字符串。即使你这样做了,当你把字符串转换回整数时,你的程序也会崩溃,因为整数无法容纳字符串的值。
我的建议是,对大整数使用一些类。不幸的是,C++中没有可用的,所以你必须自己编码或在互联网上找到一个。但是,别担心,即使你自己编码,如果你想一想,你会发现它并没有那么难。你甚至可以将你的想法与字符串结合使用,即使这不是解决这个问题的最佳方法,但在不使用太多内存的情况下,仍然会在所需时间内产生结果。
这是一个典型的高精度问题。
您可以使用无符号长-长数组,而不是字符串。像这样:
struct node
{
unsigned long long digit[100000];
}
它应该比字符串快。
但除非您有急事,否则您仍然可以使用字符串。
计算10000可能需要几天时间!。
我喜欢用字符串,因为它很容易写。
#include <bits/stdc++.h>
#pragma GCC optimize (2)
using namespace std;
const int MAXN = 90;
int n, m;
int a[MAXN];
string base[MAXN], f[MAXN][MAXN];
string sum, ans;
template <typename _T>
void Swap(_T &a, _T &b)
{
_T temp;
temp = a;
a = b;
b = temp;
}
string operator + (string s1, string s2)
{
string ret;
int digit, up = 0;
int len1 = s1.length(), len2 = s2.length();
if (len1 < len2) Swap(s1, s2), Swap(len1, len2);
while(len2 < len1) s2 = '0' + s2, len2++;
for (int i = len1 - 1; i >= 0; i--)
{
digit = s1[i] + s2[i] - '0' - '0' + up; up = 0;
if (digit >= 10) up = digit / 10, digit %= 10;
ret = char(digit + '0') + ret;
}
if (up) ret = char(up + '0') + ret;
return ret;
}
string operator * (string str, int p)
{
string ret = "0", f; int digit, mul;
int len = str.length();
for (int i = len - 1; i >= 0; i--)
{
f = "";
digit = str[i] - '0';
mul = p * digit;
while(mul)
{
digit = mul % 10 , mul /= 10;
f = char(digit + '0') + f;
}
for (int j = 1; j < len - i; j++) f = f + '0';
ret = ret + f;
}
return ret;
}
int main()
{
freopen("factorial.out", "w", stdout);
string ans = "1";
for (int i = 1; i <= 5000; i++)
{
ans = ans * i;
cout << i << "! = " << ans << endl;
}
return 0;
}
事实上,我知道问题在哪里提出。在我们相乘的时候,就有了实际的问题,当数字相乘并变得越来越大。
该代码经过测试,并给出了正确的结果。
#include <bits/stdc++.h>
using namespace std;
#define mod 72057594037927936 // 2^56 (17 digits)
// #define mod 18446744073709551616 // 2^64 (20 digits) Not supported
long long int prod_uint64(long long int x, long long int y)
{
return x * y % mod;
}
int main()
{
long long int n=14, s = 1;
while (n != 1)
{
s = prod_uint64(s , n) ;
n--;
}
}
14的扩展输出!=87178291200
逻辑应该是:
unsigned int factorial(int n)
{
unsigned int b=1;
for(int i=2; i<=n; i++){
b=b*n;
}
return b;
}
然而,b可能会溢出。所以你可以使用一个更大的积分类型。或者你可以使用浮动类型,这是不准确的,但可以容纳更大的数字。但似乎没有一个内置类型足够大。
- 在 C++ 中的数组上使用阶乘函数
- 阶乘问题在 c++ 中给出错误的输出
- 大数的阶乘给出错误的输出
- 什么模板用法在阶乘中更好
- 为什么我在C++阶乘函数中出现编译错误?
- 计算阶乘的 C++17 倍表达式中的错误
- 为什么 Lisp 中 1000 阶乘的计算如此之快(并显示正确的结果)?
- 在C++中执行 N 阶乘编译时间的 3 种不同/相同方法
- 平方模型为零,阶乘模型问题
- 阶乘元规划
- 阶乘-c++ 我想以不同的方式打印
- 阶乘函数只返回C++中输入的答案
- 计算最大数字的阶乘
- 带有自定义数字的阶乘函数不起作用
- N 阶乘中有多少位数字
- 在 C++ 中,数字阶乘的自写代码中的错误
- 程序以查找数字的阶乘并为负整数输入提供错误消息
- c++中带字符串的大数字的阶乘
- Ruby程序:在一个数字的阶乘的n次幂后面加零
- 是否有可能在编译时计算数字的阶乘,但不使用枚举?