python 求阶乘,求阶乘python方法

  python 求阶乘,求阶乘python方法

  用Python问题描述实现阶乘的三种方法

  输入正整数n,输出n!的价值。

  n!=123 *……* n .算法描述

  n!可能非常大,而计算机能表示的整数范围是有限的,所以需要使用高精度计算的方法。用数组A表示大整数A,A[0]表示A的单个位,A[1]表示A的第十位,以此类推。

  a乘以一个整数k就变成了数组a的每个元素乘以k,请注意对应的进位。

  首先,将A设为1,然后乘以2和3。当你乘以N,你得到N!的价值。输入格式

  输入一个正整数n,n=1000。输出格式

  输出n!的确切值。样例输入

  10样例输出

  3628800

  看到这个问题,我首先想到了两个简单的解决方法,一个是循环,一个是递归。

  方案一:Loop n=int(input())ns=1 for I in range(1,n ^ 1):ns=ns * iprint(ns)思路比较简单,就是定义一个变量ns给一个初始值1,然后用for loop直接相乘得到最终结果。

  解法二:递归def factorial(n):if n==1:return n else:return n * factorial(n-1)n=int(input())RES=factorial(n)print(RES)递归也比较好理解。当n==2时,返回2 * 1;n==3,返回3 *(2 * 1);n==4,返回4*(3*(2*1)).以此类推,然后把最终结果给res,打印出来。

  这两种方法都比较简单,但显然不符合题目的要求:“用数组A表示大整数A,A[0]表示A的单个位,A[1]表示A的第十位”,所以要想办法用数组来取N!结果。解3:数组n=int(input())ns=[0 for I in range(10000)]length=1 ns[0]=length=1 if n=2:for I in range(2,n 1):carry=0 for j in range(length):temp=ns[j]* I carry=int(temp/10)ns[j]=temp % 10 while carry 0:ns[length]=carry length=1 carry=int(carry/10)while length 0:length-=1 print(ns[length]

  首先定义一个ns数组来存储n!的每个数位上的值,用于循环将10000个0值加到ns上,以便于以后直接根据索引进行数组的操作。

  然后将length定义为“数组的长度”(用实值代替自动加0的那个),即N!结果的位数。

  之后,for循环也必须用于乘法,但它不同于解决方案1中的直接乘法。这里乘数(即I)乘以每一位上的数字,如果结果大于等于10,那么carry0表示当前ns的“长度”中需要一位。所以长度1就是数字1,其中进位起着判断是否进位的作用,长度代表结果。这可能有点抽象。我们通过对运行过程的分解来更直观的解释一下上面的思路。

  比如我们现在需要要求5!分为五步,即我循环5次:

  i=1 ns[0]=length=1,carry=0j in range(1)(1)j=0 temp=ns[j]* icary=ns[0]* icary=1 * 10=1 # temp是第j位乘以I,再加上j-1位乘以I所携带的值carry=int (temp/10)=1的结果。10=0 #进位=0,所以不需要进位ns[j]=temp% 10,也就是ns[0]=1% 10=1 #,只取一个位值作为第j位的值i=2 ns[0]=1,length=1,carry=0j in range(1)(1)j=0 temp=ns[j]* icary=ns[0]* icary=1 * 20=2 # temp是第j位数字乘以I再加上10=0 #进位=0,所以不需要进位ns[j]=temp% 10,也就是ns[0]=2% 10=2 #,只取一个比特值作为第j个比特#的值,所以已经是2了!的值是2 i=3 ns[0]=2,length=1,Carry=0 j在范围(1)内(1)j=0 temp=ns[j]* icary=ns[0]* icary=2 * 30=6 # temp是第j位数字乘以I,加上j-1位数字乘以I所携带的值carry=int (temp/10)=6的结果。10=0 #进位=0,所以不需要进位ns[j]=temp% 10,也就是ns[0]=6% 10=6 #,只取一个比特值作为第j个比特#的值,所以已经是3了!值为64i 6 i=4 ns[0]=6,length=1 1,Carry=0 j在范围(1)(1)j=0 temp=ns[j]* icary=ns[0]* icary=6 * 40=24 # temp是第j位乘以I,j-1位乘以I所携带的值相加的结果carry=int (temp/10)=24。10=2 #进位=20,所以需要前移2ns[j]=temp% 10,也就是ns[0]=24% 10=4 #。仅取一个比特值作为第j比特的值。j循环结束,Carry0执行while循环而carry 0: ns [length]=carry,即ns[1]=2% 10=2 #carry=2,所以向前移动2 length=1,即length=1 1=2 #位数加1进位=int(carry/10)=2/10=0 # carry=210,所以不需要继续,而循环结束length=2,ns[0]=4,ns[1]=2 #所以得到4!ns[1]*10 ns[0]的值为24。输出时可以直接倒着打印然后end= 不用每个数字乘以10*n再相加。i=5 ns[0]=4,ns[1]=2 length=2,carry=0j in range(2)(1)j=0 temp=ns[j]* icary=ns[0]* icary=4 * 50=20 # temp是第j位乘以I,j-1位乘以I所携带的值相加的结果carry=int (temp/10)=20。10=2 #进位=20,所以需要提前2ns[j]=temp% 10,也就是ns[0]=20% 10=0 #。只取一位数值作为第j位的值j=1 temp=ns[j]* icary=ns[1]* icary=2 * 52=12。是temp的第j位乘以I,加上第j-1位乘以I所携带的值的结果carry=int(temp/10)=12/10=1 # carry=10,所以需要提前1ns[j]=temp% 10,即ns[1]=12% 10=2 #。仅取一个比特值作为第j个数字的值。循环的结束。Carry0执行while循环而carry 0: ns [length]=carry,即ns[2]=1% 10=1 #carry=1,所以往前走2 length=1,即length=2 1=3 #位数加1 carry=int(carry/10)=1/10=0 # carry=110,所以不需要继续进行,而循环结束 length=3,ns [0]=0,ns [1]=2,ns [2]=1 #,所以得到5!ns[2] ns[1] ns[0]的值是120。那么,是不是发现小学学的竖式乘法过程很像呢?从低位到高位(ns[j],j在range(0,length))依次乘以乘数(I),大于十位小数(carry=temp/10 > 0)。如果我希望我的解释是清楚的。如果您有任何问题或不同的想法,请随时讨论。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: