今天无意中看到一篇博客http://www.oschina.net/code/snippet_253900_27679,作者在里面提到一个问题是通过java处理100!的结果的各位数之和为多少?
因为Java有着严格的数据类型机制,数据会越界.看到问题我的思路其实也很简单,就是把100的阶乘这个数拿到,然后拆成一位数一位数的数组,把所有数字加成合计就好了.写完发现for循环便利一个这么大的数字简直是灾难,在浏览器的控制台中看这个数字100!显示为:9.33262154439441e+157
这种指数表示的方式,代表数字的大小是9.33262154439441 * (10的157次方).这里的问题是要求这个数的各位数之和,所以0是没有运算的必要的,那么9.33262154439441e+157中e之前的数字之和才是我们需要的,这么一来就简单了.
代码如下:
<script>
function jc(x){
var jg = 0;
if(x === 1){
return 1;
}else{
jg = x * jc(x-1);
}
return jg;
}
var result = jc(100).toExponential().toString();
result = result.replace(".","");
var r = result.substr(0,result.indexOf("e"));
var arr = r.split("");
var jg = 0;
for(var i=0;i<arr.length;i++){
jg = jg + Number(arr[i]);
}
console.log(jg);
</script>
结果是60,运算速度很快,因为没有大数字的for循环.这是100!的结果,如果运算到171时,就会超出javascript中存储的极限,那个数字显示为 Infinity,表示无穷大.如果对这个问题继续有兴趣,可以看看大数阶乘.
这个计算经过网友指出确实是存在错误的,因为精度丢失的原因,指数表达不完全100!的大小.这个寻找了一下网上关于javascript进行这种大数运算的例子确实比较少,因为在一般观点里javascript就是操作页面特效的简单语言,对于计算不怎么擅长.
后来在51js上找到一段关于大数阶乘运算的代码,它将结果通过字符串的形式表现.
function factorial(n) {
var a = [1];
for (var i = 1;i<=n ;i++) {
for (var j = 0, c = 0;j<a.length || c != 0;j++ ) {
var m = (j < a.length) ? (i*a[j] + c) : c;
a[j] = m % 10;
c = (m - a[j]) / 10;
}
}
return a.reverse().join("");
}
然后再通过之前的方式计算各位数的合计,计算结果是648.这个结果和本文开篇提到的那篇博客的结果不一样的,经过我的手工验证,应该那篇博客里23!开始就计算有错误.
这类问题的核心思想不在于单纯的计算,而是对于大数的保存,确保精度不丢失,以及分治的思想.具体有兴趣可以百度大数阶乘,因为javascript设计初衷就没有为这类大数计算留有太多余地.
来源:oschina
链接:https://my.oschina.net/u/723632/blog/189621