我需要计算一个数的阶乘而不使用乘法运算符。由于这个限制,我直接尝试使用重复加法。挺管用的。然而,我的程序很难得到更大数字的阶乘。有没有更好的方法来解决这个问题?
下面是我的代码:
void main(){
unsigned long num = 0, ans = 1, temp = 1;
printf("Enter a number: ");
scanf("%lu", &num);
while (temp <= num){
int temp2 = 0, ctr = 0;
while (ctr != temp){
temp2 += ans;
ctr ++;
}
ans = temp2;
temp ++;
}
printf("%lu! is %lu\n", num, ans);
}
2条答案
按热度按时间7lrncoxx1#
您可以使用位移位和加法来实现更快(比重复加法更快)的乘法函数,以执行二进制的“长乘法”。
编辑:使用单个比特移位和加法的上述替代实现:
实际上,这是否比重复加法快取决于编译器所做的任何优化。优化编译器可以分析重复的加法并将其替换为乘法。优化编译器也可以分析上面的
mul_ull
函数的代码,并将其替换为乘法,但优化器可能更难发现。所以在实际中,优化后的重复加法算法比移位加法算法更快是完全合理的!此外,如果第二个参数
b
是相乘的数字中的较小者,则mul_ull
函数的上述实现将倾向于执行得更好,此时数字中的一个比另一个大得多(这对于阶乘计算是典型的)。执行时间大致与b
的对数成正比(当b
非零时),但也取决于b
的二进制值中1位的数量。因此,对于阶乘计算,将旧的运行乘积放在第一个参数a
中,将新的因子放在第二个参数b
中。使用上述乘法函数的阶乘函数:
上面的
factorial
函数很可能由于算术溢出而产生n
> 20的错误结果。需要66位来表示21!但是unsigned long long
仅需要64位宽(并且这通常是大多数实现的实际宽度)。编辑2023-06-07
一个稍微长一点的
factorial()
函数,如果对n
的值有相同的限制,那么它所使用的乘法次数还不到一半。此方法基于2023年3月21日编辑后的https://scicomp.stackexchange.com/q/42510中所示的方法。例如,它计算9!= 18·24·28·30 = 362880,10!= 10·18·24·28·30 = 3628800。
20jt8wwn2#
对于较大的
n
值,需要使用较大的格式。因为你不能使用乘法,所以你必须自己实现它似乎是合乎逻辑的。
在实践中,由于只需要加法,所以如果我们不寻求高效率,实现起来并不困难。
一个小问题,无论如何:你必须把输入的整数转换成一个数字数组。由于模是不允许的,我猜,我实现了它的帮助下,
snprintf
函数。结果:
注:此结果是即时提供的。