62,614
社区成员
发帖
与我相关
我的任务
分享
import java.math.BigInteger;
public class Test {
public static void main(String args[]) {
long t1, t0 = System.currentTimeMillis();
BigInteger bi = factorial(50000);
t1 = System.currentTimeMillis();
System.out.printf("time: %.3fs%n", (t1 - t0) / 1000.0);
String str = bi.toString();
output(str, 50);
}
public static BigInteger factorial(int n) {
if(n < 2) {
return BigInteger.ONE;
}
int[] oddCount = new int[Integer.numberOfTrailingZeros(Integer.highestOneBit(n))];
int shift = init(oddCount, n);
BigInteger result = BigInteger.ONE;
BigInteger bg = BigInteger.ONE;
BigInteger tmp = BigInteger.ONE;
int max = oddCount[oddCount.length - 1];
int offset = (oddCount[0] + 1) & 1;
int oddStart = 1;
while(oddStart <= max) {
tmp = tmp.multiply(new BigInteger(String.valueOf(2 * oddStart + 1)));
if(oddCount[offset] == oddStart) {
offset++;
bg = bg.multiply(tmp);
tmp = BigInteger.ONE;
result = result.multiply(bg);
}
oddStart++;
}
return result.shiftLeft(shift);
}
private static int init(int[] oddCount, int n) {
int s = n;
int r = 0;
int k = oddCount.length;
while(k > 0) {
s >>= 1;
oddCount[--k] = n - s - 1;
n = s;
r += s;
}
return r;
}
private static void output(String str, int lineLength) {
char[] chs = str.toCharArray();
int offset = 0;
while (offset < chs.length) {
int max = Math.min(chs.length - offset, lineLength);
System.out.println(new String(chs, offset, max));
offset += max;
}
}
}
public class Test {
public static void main(String[] args) {
stirlingFactorial(50000);
logFactorial(50000);
}
/**
* Stirling:
* n! = sqrt(2 * pi * n) * pow(n / e, n)
* @param n
*/
public static void stirlingFactorial(int n) {
double a = n * Math.log10(n / Math.E);
double s = 0.5 * Math.log10(2 * Math.PI * n);
double base10 = a + s;
int exponent = (int)base10;
double base = Math.pow(10, base10 - exponent);
System.out.println(n + "! = " + base + " * 10^" + exponent);
}
/**
* n! = 1 * 2 * 3 * ... * (n - 1) * n
* log(n!) = log(1) + log(2) + log(3) + ... + log(n - 1) + log(n)
* @param n
*/
public static void logFactorial(int n) {
double sum = 0;
for(int i = 1; i <= n; i++) {
sum += Math.log10(i);
}
int exponent = (int)sum;
double base = Math.pow(10, sum - exponent);
System.out.println(n + "! = " + base + " * 10^" + exponent);
}
}
上面程序输出:
Stirling 公式
50000! = 3.347314930703388 * 10^213236
log 法
50000! = 3.3473205027452186 * 10^213236
int n =;
int sum = 1;
if (n < 0)
{
System.out.println("n is overflow");
return ;
}
else if (n == 0)
{
n = 0;
}
else {
for (int i = 1; i < n ; i ++)
{
sum = sum * i;
if(sum>50000)
输出n
当然可以int型放不下那么大,但思路是这样的
}