n的阶乘问题--阶乘位数--阶乘末尾0的个数

初来乍到,望高手指教!

原有解决n的阶乘的方式--迭代,如果是大数据的话,迭代会吃掉大量内存,导致内存溢出;用平时的迭代解决n的阶乘问题:在计算21的阶乘时,结果已然为负数,超出整型数据表示范围。计算34的阶乘是,结果已然为0;


此段代码将n的阶乘问题解决,实现无限大数的阶乘!(“无限”两字有点牵强,数字太大是否导致内存溢出,暂未考虑)。解决方案:
1、数据的表示用字符串
2、在计算数据相乘、相加时采用字符串计算
a、将字符串解析成字符数组,利用数字字符-48获得数值;
b、将字符串按位取出,解析成数值类型;


public class Factorial {

private int n;

public Factorial(int n) {
this.n = n;
}

//计算n的阶乘所得的结果有多少位数
//result通过factorial(n)获取

public int calFactorialTrialNum(String result) {
char[] arrStr = result.toCharArray();
return arrStr.length;
}

//计算n的阶乘所得结果末尾有多少个零
//result通过factorial(n)获取

public int calFactorialTrialZeroNum(String result) {

char[] arrStr = result.toCharArray();

int count = 0;

for (int i = arrStr.length - 1; i >= 0; i--) {
if (arrStr[i] == '0') {
count++;
} else {
return count;
}
}
return count;
}

//用循环代替迭代,计算n的阶乘的主体
public String factorial(int n) {

if (n <= 0) {
return null;
}
String result = "1";
for (int i = 1; i <= n; i++) {
result = calculate(i, result);
}

return result;
}

//此方法相当于 n!= n*(n-1)! 此时(n-1)! = str
public String calculate(int n, String str) {

char[] arrStr = str.toCharArray();
char[] numStr = ("" + n).toCharArray();
int numZero = 1;
StringBuilder result = new StringBuilder("");

for (int i = numStr.length - 1; i >= 0; i--) {

int calNum = numStr[i] - 48;
int binary = 0;
StringBuilder temp = new StringBuilder("");

//当n为两位数或更多位数的时候,对高位进行错位
//因此时计算结果与真实数据刚好逆序,所以在字符串开头拼接0
for (int num = 2; num <= numZero; num++) {
temp.append("0");
}
for (int j = arrStr.length - 1; j >= 0; j--) {
int calRes = (arrStr[j] - 48) * calNum + binary;
if (calRes < 10) {
temp.append(calRes);
binary = 0;
} else {
temp.append(calRes % 10);
binary = calRes / 10;
}
if (j == 0 && binary != 0) {
temp.append(binary);
}
}
if (result.toString().equals("")) {
result = temp;
} else {
result = addStringToString(result.toString(), temp.toString());
}
numZero++;
}

return result.reverse().toString();
}


//将两个字符串进行解析后求和
//result 表示 n = 123 当计算1即n的最高位时,1以下位数与目标字符串的乘积之和
//temp 表示 n = 123 当计算1即n的最高位时,1与目标字符串的乘积
public StringBuilder addStringToString(String result, String temp) {

int length = result.length() < temp.length() ? result.length() : temp
.length();
char[] tempArr = temp.toCharArray();
char[] resultArr = result.toCharArray();

int binary = 0;
StringBuilder resultBuilder = new StringBuilder("");

for (int i = 0; i < length; i++) {
int addRes = (resultArr[i] - 48) + (tempArr[i] - 48) + binary;
if (addRes < 10) {
resultBuilder.append(addRes);
binary = 0;
} else {
resultBuilder.append(addRes % 10);
binary = addRes / 10;
}
}
if (length == result.length() && length == temp.length()) {
if (binary != 0) {
resultBuilder.append(binary);
}
} else if (length == result.length()) {
if (binary != 0) {
String str = addIntToString(binary, temp.substring(length));
resultBuilder.append(str);
} else {
resultBuilder.append(temp.substring(length));
}
} else if (length == temp.length()) {
if (binary != 0) {
String str = addIntToString(binary, result.substring(length));
resultBuilder.append(str);
} else {
resultBuilder.append(result.substring(length));
}
}

return resultBuilder;
}


//当上面一个函数中的两个字符串长度不一样或有进位时调用下面的函数进行高位处理

private String addIntToString(int temp, String str) {

char[] arrStr = str.toCharArray();
StringBuilder builder = new StringBuilder("");

for (int i = 0; i < arrStr.length; i++) {
int arrRes = temp + (arrStr[i] - 48);
if (arrRes >= 10) {
temp = arrRes / 10;
builder.append(arrRes % 10);
} else {
temp = 0;
builder.append(arrRes);
}
}
if (temp != 0) {
builder.append(temp);
}
return builder.toString();
}

public static void main(String[] args){

Factorial fac = new Factorial(1000);

String str = fac.factorial(fac.n);

int trailZeroNum = fac.calFactorialTrialZeroNum(str);
int trailNum = fac.calFactorialTrialNum(str);

System.out.println(trailZeroNum);
System.out.println(trailNum);


}

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值