我还没找到它。我错过了什么? 我知道一个阶乘方法是初学者的常见示例程序。但是,重新使用这个标准实现是不是很有用? 我可以使用标准类型(int,long ...)和BigInteger / BigDecimal这样的方法。
答案 0 :(得分:53)
Apache Commons Math在MathUtils类中有一些因子方法。
答案 1 :(得分:39)
public class UsefulMethods {
public static long factorial(int number) {
long result = 1;
for (int factor = 2; factor <= number; factor++) {
result *= factor;
}
return result;
}
}
HoldOffHunger的大数字版本:
public static BigInteger factorial(BigInteger number) {
BigInteger result = BigInteger.valueOf(1);
for (long factor = 2; factor <= number.longValue(); factor++) {
result = result.multiply(BigInteger.valueOf(factor));
}
return result;
}
答案 2 :(得分:25)
我认为为factorial提供库函数不会有用。对有效的因子实现进行了大量研究。 Here is a handful of implementations.
答案 3 :(得分:22)
在实践中很少需要赤裸裸的阶乘。大多数情况下,您需要以下其中一项:
1)将一个阶乘除以另一个阶乘,或
2)近似浮点答案。
在这两种情况下,您都可以使用简单的自定义解决方案。
在情况(1)中,例如,如果x = 90! / 85!,然后你将计算结果就像x = 86 * 87 * 88 * 89 * 90,而不需要保持90!在记忆中:)
在案例(2)中,谷歌搜索“斯特林的近似值”。
答案 4 :(得分:11)
使用Guava的BigIntegerMath
如下:
BigInteger factorial = BigIntegerMath.factorial(n);
答案 5 :(得分:6)
因为factorial增长如此之快,如果使用递归,堆栈溢出不是问题。其实价值20!是Java中可以代表的最长的一个。因此,如果n太大,以下方法将计算factorial(n)或抛出IllegalArgumentException。
public long factorial(int n) {
if (n > 20) throw new IllegalArgumentException(n + " is out of range");
return (1 > n) ? 1 : n * factorial(n - 1);
}
另一种(更酷)的方法是使用Java 8的流库,如下所示:
public long factorial(int n) {
if (n > 20) throw new IllegalArgumentException(n + " is out of range");
return LongStream.rangeClosed(1, n).reduce(1, (a, b) -> a * b);
}
答案 6 :(得分:6)
我相信这将是最快的方式,通过查找表:
private static final long[] FACTORIAL_TABLE = initFactorialTable();
private static long[] initFactorialTable() {
final long[] factorialTable = new long[21];
factorialTable[0] = 1;
for (int i=1; i<factorialTable.length; i++)
factorialTable[i] = factorialTable[i-1] * i;
return factorialTable;
}
/**
* Actually, even for {@code long}, it works only until 20 inclusively.
*/
public static long factorial(final int n) {
if ((n < 0) || (n > 20))
throw new OutOfRangeException("n", 0, 20);
return FACTORIAL_TABLE[n];
}
对于原生类型long
(8个字节),它最多只能容纳20!
20! = 2432902008176640000(10) = 0x 21C3 677C 82B4 0000
显然,21!
会导致溢出。
因此,对于原生类型long
,只允许最大20!
,有意义且正确。
答案 7 :(得分:6)
简短回答是:使用递归。
您可以创建一个方法并在递归的同一方法内调用该方法:
public class factorial {
public static void main(String[] args) {
System.out.println(calc(10));
}
public static long calc(long n) {
if (n <= 1)
return 1;
else
return n * calc(n - 1);
}
}
答案 8 :(得分:6)
Apache Commons Math包有a factorial method,我想你可以使用它。
答案 9 :(得分:5)
虽然阶乘为初级程序员做了很好的练习,但在大多数情况下它们并不是很有用,并且每个人都知道如何编写阶乘函数,所以它们通常不是平均值库。
答案 10 :(得分:3)
试试这个
public static BigInteger factorial(int value){
if(value < 0){
throw new IllegalArgumentException("Value must be positive");
}
BigInteger result = BigInteger.ONE;
for (int i = 2; i <= value; i++) {
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}
答案 11 :(得分:2)
You can use recursion.
data.frame
and then after you create the method(function) above:
levels_together group_by_var kernel_type
1 0.051 tw b
2 0.055 tw b
3 0.053 fif b
4 0.046 fif b
5 0.053 sev b
6 0.050 sev b
7 0.059 tw e
8 0.056 tw e
9 0.052 fif e
10 0.044 fif e
11 0.058 sev e
12 0.053 sev e
13 0.052 tw p
14 0.053 tw p
15 0.051 fif p
16 0.044 fif p
17 0.051 sev p
18 0.050 sev p
答案 12 :(得分:2)
我找到了一个惊人的技巧,可以在实际乘法的一半中找到阶乘。
请耐心等待,因为这是一个很长的帖子。
对于偶数: 要将偶数乘以一半,最终会得到n / 2个因子。第一个因素将是您采用阶乘的数字,然后下一个将是该数字加上该数字减去2。下一个数字将是前一个数字加上持续增加的数字减去两个。 当您添加的最后一个号码为2(即2)时,您就完成了。这可能没有多大意义,所以让我举个例子。
8! = 8 * (8 + 6 = 14) * (14 + 4 = 18) * (18 + 2 = 20)
8! = 8 * 14 * 18 * 20 which is **40320**
请注意,我从8开始,然后我添加的第一个数字是6,然后是4,然后是2,每个数字加上比之前添加的数字少两个。此方法相当于将最小数字乘以最大数字,只需乘以较少的乘法,如下所示:
8! = 1 * 2 * 3 * 4 * 5 * 6 * 7 *
8! = (1 * 8) * (2 * 7) * (3 * 6) * (4 * 5)
8! = 8 * 14 * 18 * 20
简单不是:)
现在对于奇数:如果数字是奇数,则添加是相同的,就像每次减去两个,但是你停在三。然而,因素的数量会发生变化。如果将数字除以2,最终会得到一些以.5结尾的数字。原因是如果我们将两端相乘,那么我们就会留下中间的数字。基本上,这可以通过求解等于数除以2的多个因子来解决。对于没有数学背景的人来说,这可能没什么意义,所以让我举一个例子:
9! = 9 * (9 + 7 = 16) * (16 + 5 = 21) * (21 + 3 = 24) * (roundUp(9/2) = 5)
9! = 9 * 16 * 21 * 24 * 5 = **362880**
注意:如果你不喜欢这种方法,你也可以在奇数之前取偶数的阶乘(在这种情况下为8)并乘以奇数(即9!= 8!* 9)。
现在让我们用Java实现它:
public static int getFactorial(int num)
{
int factorial=1;
int diffrennceFromActualNum=0;
int previousSum=num;
if(num==0) //Returning 1 as factorial if number is 0
return 1;
if(num%2==0)// Checking if Number is odd or even
{
while(num-diffrennceFromActualNum>=2)
{
if(!isFirst)
{
previousSum=previousSum+(num-diffrennceFromActualNum);
}
isFirst=false;
factorial*=previousSum;
diffrennceFromActualNum+=2;
}
}
else // In Odd Case (Number * getFactorial(Number-1))
{
factorial=num*getFactorial(num-1);
}
return factorial;
}
isFirst
是一个声明为static的布尔变量;它用于我们不想改变之前总和的第一种情况。
尝试使用偶数和奇数。
答案 13 :(得分:1)
我能想到的唯一商业用途是Erlang B和Erlang C公式,并不是每个人都在呼叫中心或电话公司工作。功能对业务的有用性似乎经常决定了语言中出现的内容 - 查看主要语言中的所有数据处理,XML和Web功能。
很容易为这样的事情保留一个因子片段或库函数。
答案 14 :(得分:1)
/**
import java liberary class
*/
import java.util.Scanner;
/* class to find factorial of a number
*/
public class factorial
{
public static void main(String[] args)
{
// scanner method for read keayboard values
Scanner factor= new Scanner(System.in);
int n;
double total = 1;
double sum= 1;
System.out.println("\nPlease enter an integer: ");
n = factor.nextInt();
// evaluvate the integer is greater than zero and calculate factorial
if(n==0)
{
System.out.println(" Factorial of 0 is 1");
}
else if (n>0)
{
System.out.println("\nThe factorial of " + n + " is " );
System.out.print(n);
for(int i=1;i<n;i++)
{
do // do while loop for display each integer in the factorial
{
System.out.print("*"+(n-i) );
}
while ( n == 1);
total = total * i;
}
// calculate factorial
sum= total * n;
// display sum of factorial
System.out.println("\n\nThe "+ n +" Factorial is : "+" "+ sum);
}
// display invalid entry, if enter a value less than zero
else
{
System.out.println("\nInvalid entry!!");
}System.exit(0);
}
}
答案 15 :(得分:1)
一种相当简单的方法
for ( int i = 1; i < n ; i++ )
{
answer = answer * i;
}
答案 16 :(得分:1)
我们只用一行来计算它:
Long factorialNumber = LongStream.rangeClosed(2, N).reduce(1, Math::multiplyExact);
答案 17 :(得分:1)
因子是高度增加的离散函数。所以我认为使用BigInteger比使用int更好。 我已经实现了以下代码来计算非负整数的阶乘。我使用递归代替使用循环。
public BigInteger factorial(BigInteger x){
if(x.compareTo(new BigInteger("1"))==0||x.compareTo(new BigInteger("0"))==0)
return new BigInteger("1");
else return x.multiply(factorial(x.subtract(new BigInteger("1"))));
}
这里大整数的范围是
-2^Integer.MAX_VALUE (exclusive) to +2^Integer.MAX_VALUE,
where Integer.MAX_VALUE=2^31.
但是,通过使用无符号的BigInteger,上面给出的阶乘方法的范围可以扩展到两倍。
答案 18 :(得分:1)
您也可以使用递归版本。
static int myFactorial(int i) {
if(i == 1)
return;
else
System.out.prinln(i * (myFactorial(--i)));
}
递归通常效率较低,因为必须推送和弹出递归,因此迭代更快。另一方面,递归版本使用较少或没有局部变量,这是有利的。
答案 19 :(得分:1)
计算阶乘的一种非常简单的方法:
private double FACT(double n) {
double num = n;
double total = 1;
if(num != 0 | num != 1){
total = num;
}else if(num == 1 | num == 0){
total = 1;
}
double num2;
while(num > 1){
num2 = num - 1;
total = total * num2;
num = num - 1;
}
return total;
}
我使用了double,因为它们可以容纳大量数字,但你可以使用任何其他类型,如int,long,float等。
P.S。这可能不是最好的解决方案,但我是编码的新手,我花了很长时间才找到一个可以计算阶乘的简单代码,所以我必须自己写这个方法,但是我把它放在这里,所以它有助于像我这样的其他人。
答案 20 :(得分:0)
public static long factorial(int number) {
if (number < 0) {
throw new ArithmeticException(number + " is negative");
}
long fact = 1;
for (int i = 1; i <= number; ++i) {
fact *= i;
}
return fact;
}
使用递归。
public static long factorial(int number) {
if (number < 0) {
throw new ArithmeticException(number + " is negative");
}
return number == 0 || number == 1 ? 1 : number * factorial(number - 1);
}
答案 21 :(得分:0)
使用递归是最简单的方法。如果我们想找到的阶乘 N,由于阶乘,我们必须考虑N = 1和N> 1的两种情况 我们继续乘以N,N-1,N-2 ,,,,,直到1。如果我们转到N = 0,我们将得到0 寻找答案。为了阻止阶乘达到零,以下 使用递归方法。在阶乘函数内部,当N> 1时,返回 值乘以阶乘函数的另一个启动。这个 将保持代码递归调用factorial()直到到达 N = 1.对于N = 1的情况,它将返回N(= 1)本身以及所有先前构建的 返回的乘积N s的乘积乘以N = 1。因此给 阶乘结果。
static int factorial(int N) {
if(N > 1) {
return n * factorial(N - 1);
}
// Base Case N = 1
else {
return N;
}
答案 22 :(得分:0)
使用动态编程很有效
如果要使用它一次又一次地计算(例如缓存)
Java代码:
int fact[]=new int[n+1]; //n is the required number you want to find factorial for.
int factorial(int num)
{
if(num==0){
fact[num]=1;
return fact[num];
}
else
fact[num]=(num)*factorial(num-1);
return fact[num];
}
答案 23 :(得分:0)
使用 Java 9+,您可以使用此解决方案。这使用 BigInteger,非常适合保存大数。
...
import java.math.BigInteger;
import java.util.stream.Stream;
...
String getFactorial(int n) {
return Stream.iterate(BigInteger.ONE, i -> i.add(BigInteger.ONE)).parallel()
.limit(n).reduce(BigInteger.ONE, BigInteger::multiply).toString();
}
答案 24 :(得分:0)
只是为了好玩:
与FileNotFoundError: [Errno 2] No such file or directory: 'cmake': 'cmake'
一起使用的单线析因方法:
BigInteger
答案 25 :(得分:0)
带递归:
public static int factorial(int n)
{
if(n == 1)
{
return 1;
}
return n * factorial(n-1);
}
with while循环:
public static int factorial1(int n)
{
int fact=1;
while(n>=1)
{
fact=fact*n;
n--;
}
return fact;
}
答案 26 :(得分:0)
我从EDX那里得到了它!它叫做递归
public static int factorial(int n) {
if (n == 1) {
return 1;
} else {
return n * factorial(n-1);
}
}
答案 27 :(得分:0)
while循环(对于小数字)
public class factorial {
public static void main(String[] args) {
int counter=1, sum=1;
while (counter<=10) {
sum=sum*counter;
counter++;
}
System.out.println("Factorial of 10 is " +sum);
}
}
答案 28 :(得分:0)
public int factorial(int num) {
if (num == 1) return 1;
return num * factorial(num - 1);
}
答案 29 :(得分:0)
我们需要迭代实现。如果我们以递归方式实现,如果输入变得非常大(即20亿),它将导致StackOverflow。我们需要使用未绑定的大小数字,例如BigInteger,以避免当因子数大于给定类型的最大数(即int为20亿)时的算术溢出。您可以使用int最多14个阶乘,最长20个 溢出之前的阶乘。
public BigInteger getFactorialIteratively(BigInteger input) {
if (input.compareTo(BigInteger.ZERO) <= 0) {
throw new IllegalArgumentException("zero or negatives are not allowed");
}
BigInteger result = BigInteger.ONE;
for (BigInteger i = BigInteger.ONE; i.compareTo(input) <= 0; i = i.add(BigInteger.ONE)) {
result = result.multiply(i);
}
return result;
}
如果您无法使用BigInteger,请添加错误检查。
public long getFactorialIteratively(long input) {
if (input <= 0) {
throw new IllegalArgumentException("zero or negatives are not allowed");
} else if (input == 1) {
return 1;
}
long prev = 1;
long result = 0;
for (long i = 2; i <= input; i++) {
result = prev * i;
if (result / prev != i) { // check if result holds the definition of factorial
// arithmatic overflow, error out
throw new RuntimeException("value "+i+" is too big to calculate a factorial, prev:"+prev+", current:"+result);
}
prev = result;
}
return result;
}
答案 30 :(得分:0)
public static int fact(int i){
if(i==0)
return 0;
if(i>1){
i = i * fact(--i);
}
return i;
}