มีวิธีการคำนวณแฟกทอเรียลใน Java หรือไม่?


105

ฉันยังไม่พบมัน ฉันพลาดอะไรไปหรือเปล่า? ฉันรู้ว่าวิธีแฟกทอเรียลเป็นโปรแกรมตัวอย่างทั่วไปสำหรับผู้เริ่มต้น แต่จะไม่มีประโยชน์ที่จะมีการนำมาตรฐานนี้ไปใช้ซ้ำ? ฉันสามารถใช้วิธีดังกล่าวกับประเภทมาตรฐาน (เช่น int, long ... ) และกับ BigInteger / BigDecimal ด้วย

คำตอบ:


26

ฉันไม่คิดว่าการมีฟังก์ชันไลบรารีสำหรับแฟกทอเรียลจะเป็นประโยชน์ มีงานวิจัยมากมายเกี่ยวกับการใช้งานแฟกทอเรียลที่มีประสิทธิภาพ นี่คือการนำไปใช้งานจำนวนหนึ่ง


190
เหตุใดจึงไม่มีประโยชน์ที่จะมีฟังก์ชันไลบรารีสำหรับแฟกทอเรียล
กลางดึก

17
มีคนจำนวนไม่น้อยที่ต้องการแฟกทอเรียลในโค้ดจริง หากคุณทำเช่นนั้นคุณอาจกำลังทำคณิตศาสตร์หรือสถิติขั้นสูงซึ่งในกรณีนี้คุณมักจะใช้ไลบรารีคณิตศาสตร์ที่มีการใช้งานแฟกทอเรียลแบบพิเศษอยู่แล้ว
mikera

3
ฟังก์ชันแกมมามีประโยชน์มากซึ่งเป็นเหตุผลว่าทำไมจึงรวมอยู่ในไลบรารีมาตรฐาน C ++
Columbo

2
ฟังดูแล้วว่า @KarlthePagan หมายความว่าไม่มีประโยชน์ที่จะมีฟังก์ชันไลบรารีมาตรฐานสำหรับแฟกทอเรียล - ถูกต้องหรือไม่?
dantiston

ดังนั้นพวกเขาจะถามคุณในการสัมภาษณ์เพื่อดูว่าคุณสามารถทำเองได้หรือไม่ * กรณีของฉัน
moldovean

60

Apache Commons MathมีวิธีการแฟกทอเรียลสองสามวิธีในคลาสMathUtils


1
ใช่. สิ่งที่ดี. มีการใช้แฟกทอเรียลสำหรับจำนวนทศนิยมและจำนวนที่ไม่เป็นตัวเลข (MathUtils.factorial (int) และ MathUtils.factorialDouble (int)) และยังมีประโยชน์จากลอการิทึมธรรมชาติของ n! (MathUtils.factorialLog (int))
Tomasz Błachowicz

3
มันอยู่ใน ArithmeticUtils ในขณะนี้
MarianP

6
ArithmeticUtils.factorial เลิกใช้งานแล้วตอนนี้เอทีเอ็มใช้CombinatoricsUtils.factorial
Victor Häggqvist

กรุณาอย่าใช้ลิงค์! พวกเขามักจะหายไป (เช่นเดียวกับที่มีทั้งหมด)
SMBiggs

1
@ScottBiggs ลิงก์ทั้งสองในคำตอบใช้งานได้ดี
Bill the Lizard

40
public class UsefulMethods {
    public static long factorial(int number) {
        long result = 1;

        for (int factor = 2; factor <= number; factor++) {
            result *= factor;
        }

        return result;
    }
}

Big Numbers โดย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;
}

นอกจากนี้คุณสมมติว่าคุณต้องการแฟกทอเรียลของจำนวนเต็ม
แอนดรูว์

โซลูชันนี้ควรใช้คลาส BigInteger
Oleg Abrazhaev

2
เวอร์ชันตัวเลขขนาดใหญ่: แฟกทอเรียล BigInteger แบบคงที่สาธารณะ (BigInteger n) {BigInteger factorial = BigInteger.valueOf (1); สำหรับ (int i = 1; i <= n.intValue (); i ++) {factorial = factorial.multiply (BigInteger.valueOf (i)); } ส่งคืนแฟกทอเรียล; }
HoldOffHunger

23

แทบไม่จำเป็นต้องใช้แฟกทอเรียลแบบเปลือยเปล่าในทางปฏิบัติ ส่วนใหญ่คุณจะต้องมีสิ่งใดสิ่งหนึ่งต่อไปนี้:

1) หารแฟคทอเรียลหนึ่งตัวโดยอีกตัวหนึ่งหรือ

2) คำตอบจุดลอยตัวโดยประมาณ

ในทั้งสองกรณีคุณจะดีขึ้นด้วยโซลูชันที่กำหนดเองง่ายๆ

ในกรณี (1) ให้พูดว่าถ้า x = 90! / 85! แล้วคุณจะคำนวณผลลัพธ์เช่นเดียวกับ x = 86 * 87 * 88 * 89 * 90 โดยไม่จำเป็นต้องถือ 90! ในความทรงจำ :)

ในกรณีที่ (2) google สำหรับ "การประมาณของสเตอร์ลิง"


3
ตัวอย่างตัวอย่าง: การคำนวณจำนวนการเรียงสับเปลี่ยนด้วยองค์ประกอบ N จำเป็นต้องใช้แฟกทอเรียลเปลือยและจำเป็นหากคุณต้องการจัดสรรโครงสร้างเพื่อเก็บการเรียงสับเปลี่ยน
Mark Jeronimus

จุดดี! คำถามแรกของฉันคือถ้า 90! / 85! ง่ายลงเนื่องจากตัวส่วนร่วมของ 5 แต่จริงๆแล้วมันเป็นตัวส่วนร่วมของ 85! 90! / 85! = 90 * 89 * 88 * 87 * 86 * 85! / 85!. คุณจะเห็นได้ชัดเจนขึ้นในความเท่าเทียมกันนั้น
HoldOffHunger


6

แม้ว่าแฟกทอเรียลจะเป็นแบบฝึกหัดที่ดีสำหรับโปรแกรมเมอร์มือใหม่ แต่ในกรณีส่วนใหญ่ก็ไม่ได้มีประโยชน์มากนักและทุกคนก็รู้วิธีเขียนฟังก์ชันแฟกทอเรียลดังนั้นโดยทั่วไปจึงไม่อยู่ในไลบรารีทั่วไป


6
ฉันเห็นด้วยกับคุณมีฟังก์ชันทางคณิตศาสตร์ที่สำคัญกว่านี้ แต่ในสายตาของฉันวิธีนี้ควรเป็นมาตรฐานเพื่อให้ผู้คนสามารถนำกลับมาใช้ใหม่ได้ ไม่จำเป็นต้องใช้หลายครั้งโดยคนหลายคน เพื่อจุดประสงค์ทางการศึกษาที่อาจทำได้ แต่สำหรับการทำงานทุกวันมันล้าสมัย นี่คือความคิดเห็นของฉัน. ยังไงก็ขอบคุณที่ตอบ ฉันจะทำด้วยตัวเอง - อีกครั้ง

ประโยชน์ของการกำหนดมาตรฐานที่คุณเสนอคืออะไร? การเพิ่มวิธีการลงในไลบรารีมาตรฐานไม่ใช่การไม่มีค่าใช้จ่าย ตามที่คนอื่น ๆ ชี้ให้เห็นไม่มีทางออกที่ดีที่สุดเพียงวิธีเดียว คุณเสนอให้สร้างเป็นภาษาใด การมีวิธีการในไลบรารีมาตรฐานจะไม่ช่วยให้คุณประหยัดเวลาในการทำความเข้าใจปัญหาของคุณและเมื่อคุณทำเสร็จแล้วคุณสามารถเลือกการใช้งานที่เหมาะสมกับงานได้เช่นกัน
Matt G

2
"... และทุกคนรู้วิธีการเขียนฟังก์ชันแฟกทอเรียล" Chaosinmotion.com/blog/?p=622
James P.

4
ไม่เห็นด้วย. จำเป็นต้องใช้แฟกทอเรียลสำหรับCombinatoricsซึ่งจำเป็นในหลาย ๆ ด้านของการออกแบบซอฟต์แวร์ อาร์กิวเมนต์ที่ไม่รวมแฟกทอเรียลในไลบรารีคณิตศาสตร์ในตัวเป็นอาร์กิวเมนต์เดียวกับที่ไม่มีไลบรารีคณิตศาสตร์ในตัว
LateralFractal

ช่างเป็นตรรกะที่โดดเด่น เป็นตัวเอกอย่างแน่นอน น่าเสียดายที่นักออกแบบชั้นเรียน java.lang.Math ไม่รู้เรื่องนี้เมื่อพวกเขารวมวิธีการ abs () ไว้ใน lib นั้น
Igor Soudakevitch

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!จะทำให้ล้น

ดังนั้นสำหรับประเภทเนทีlong20!จะอนุญาตให้มีความหมายและถูกต้องได้สูงสุดเท่านั้น


1
เป็นความคิดที่ดีทีเดียว เมื่อพิจารณาว่าแฟกทอเรียล 20 แรกนั้นน่าจะเพียงพอฉันจะเพิ่มค่าคงที่คงที่ (ไม่จำเป็นต้องคำนวณทุกครั้งที่เปิดแอป) ให้กับคลาสคณิตศาสตร์ด้วยข้อมูลเหล่านั้น ความจริงที่ว่ามีคนจำนวนไม่น้อยที่ต้องการแฟกทอเรียลในโค้ดของพวกเขาเป็นข้ออ้างที่ไม่ดีที่จะไม่รองรับในคลาสคณิตศาสตร์
TG

6

เนื่องจากแฟกทอเรียลเติบโตอย่างรวดเร็วสแต็กล้นจึงไม่ใช่ปัญหาหากคุณใช้การเรียกซ้ำ ในความเป็นจริงมูลค่า 20! เป็นสิ่งที่ใหญ่ที่สุดที่สามารถแสดงใน Java แบบยาว ดังนั้นวิธีการต่อไปนี้จะคำนวณ factorial (n) หรือโยน IllegalArgumentException ถ้า n ใหญ่เกินไป

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);
}

อ่านเพิ่มเติมเกี่ยวกับ Factorials โดยใช้สตรีมของ Java 8



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);
    }
}

5
ฟังก์ชั่นแบบวนซ้ำเป็นสิ่งที่ดี แต่ถ้ามีคนลองนับ Fatiorial ที่ใหญ่มากพวกเขาจะจบลงด้วย StackOverflowException;) + ฉันไม่แน่ใจ แต่ฉันคิดว่าการเรียกซ้ำช้ากว่าวิธีการวนซ้ำแบบเก่าที่ดี)
TG

คุณจะรู้ได้อย่างไรว่ามันจะจบลงด้วยข้อยกเว้น stackoverflow? @TG
gumuruh

2
นั่นเป็นเรื่องง่าย การเรียกซ้ำแต่ละครั้งจะวางตำแหน่งปัจจุบันบนสแต็กดังนั้นโปรแกรมจะมี 'หน่วยความจำ' ของสถานที่ที่จะย้อนกลับไปหลังจากการเรียกเมธอดเสร็จสิ้น สแต็คมีขีด จำกัด จะลองด้วยตัวคุณเองลองโค้ดข้างต้นเปลี่ยนแปลงSystem.out.println(calc(10));ไปSystem.out.println(calc(Long.MAX_VALUE));คุณควรจะได้ stactrace ยาวสวย :)
TG

@TG เพื่อความชัดเจนฉันลองใช้วิธีการเรียกซ้ำซึ่งใช้งานBigIntegerได้ ฉันพยายามคำนวณแฟกทอเรียลของจำนวน8020ซึ่งให้ผลลัพธ์613578884952214809325384...ซึ่งมี27831ตำแหน่งทศนิยม ดังนั้นแม้ว่าจะทำงานกับตัวเลขที่Stackoverflowจะไม่มีการโยนจำนวนมาก แน่นอนว่าคุณพูดถูก แต่ฉันสงสัยว่ามีตัวเลขที่ใหญ่และใช้งานได้จริง :-)
Moritz Schmidt

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;
}

3
ผมเชื่อว่ามีข้อผิดพลาดในห่วงสำหรับ: i <= valueมันควรจะเป็น (int i = 2; i <= value; i++)สำหรับวงจะได้รับการปรับเล็กน้อยเพื่อ
คริส

2

ฉันพบเคล็ดลับที่น่าทึ่งในการหาแฟกทอเรียลเพียงครึ่งเดียวของการคูณจริง

โปรดอดทนเนื่องจากนี่เป็นโพสต์ที่ยาวสักหน่อย

สำหรับเลขคู่: หากต้องการลดการคูณด้วยเลขคู่ลงครึ่งหนึ่งคุณจะได้ปัจจัย n / 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

เรียบง่ายใช่ไหม :)

ตอนนี้สำหรับเลขคี่:หากจำนวนเป็นเลขคี่การเพิ่มจะเหมือนกันเช่นเดียวกับที่คุณลบสองครั้งในแต่ละครั้ง แต่คุณหยุดที่สาม จำนวนของปัจจัยเปลี่ยนแปลงอย่างไรก็ตาม หากคุณหารจำนวนด้วยสองคุณจะได้ตัวเลขที่ลงท้ายด้วย. 5 เหตุผลก็คือถ้าเราคูณปลายเข้าด้วยกันเราจะเหลือเลขกลาง โดยพื้นฐานแล้วสิ่งนี้สามารถแก้ไขได้โดยการแก้ปัจจัยหลายอย่างเท่ากับจำนวนที่หารด้วยสองแล้วปัดขึ้น สิ่งนี้อาจไม่สมเหตุสมผลนักหากไม่มีพื้นฐานทางคณิตศาสตร์ดังนั้นให้ฉันทำตัวอย่าง:

9! = 9 * (9 + 7 = 16) * (16 + 5 = 21) * (21 + 3 = 24) * (roundUp(9/2) = 5)

9! = 9 * 16 * 21 * 24 * 5 = **362880**

หมายเหตุ:หากคุณไม่ชอบวิธีนี้คุณสามารถนำแฟกทอเรียลของจำนวนคู่ก่อนเลขคี่ (แปดในกรณีนี้) แล้วคูณด้วยจำนวนคี่ (เช่น 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เป็นตัวแปรบูลีนที่ประกาศเป็นแบบคงที่ ใช้สำหรับกรณีแรกที่เราไม่ต้องการเปลี่ยนผลรวมก่อนหน้านี้

ลองใช้เลขคู่และเลขคี่


2

คุณสามารถใช้การเรียกซ้ำ

public static int factorial(int n){    
      if (n == 0)    
        return 1;    
      else    
        return(n * factorial(n-1));    
     }

จากนั้นหลังจากที่คุณสร้างเมธอด (ฟังก์ชัน) ด้านบน:

System.out.println(factorial(number of your choice));  
    //direct example
    System.out.println(factorial(3));

1

การใช้งานทางธุรกิจเพียงอย่างเดียวสำหรับแฟกทอเรียลที่ฉันคิดได้คือสูตร Erlang B และ Erlang C ไม่ใช่ทุกคนที่ทำงานในคอลเซ็นเตอร์หรือ บริษัท โทรศัพท์ ประโยชน์ของคุณลักษณะสำหรับธุรกิจมักจะกำหนดสิ่งที่ปรากฏในภาษา - ดูที่การจัดการข้อมูล XML และฟังก์ชันเว็บทั้งหมดในภาษาหลัก ๆ

มันเป็นเรื่องง่ายที่จะเก็บข้อมูลโค้ดแฟกทอเรียลหรือฟังก์ชันไลบรารีไว้สำหรับอะไรทำนองนี้


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 ฯลฯ

ป.ล. นี่อาจไม่ใช่วิธีแก้ปัญหาที่ดีที่สุด แต่ฉันยังใหม่กับการเขียนโค้ดและฉันต้องใช้เวลานานในการค้นหาโค้ดง่ายๆที่สามารถคำนวณแฟกทอเรียลได้ดังนั้นฉันจึงต้องเขียนวิธีการด้วยตัวเอง แต่ฉันใส่สิ่งนี้ไว้ที่นี่เพื่อช่วยให้คนอื่น ๆ เช่นฉัน .


1

คุณสามารถใช้เวอร์ชันการเรียกซ้ำได้เช่นกัน

static int myFactorial(int i) {
    if(i == 1)
        return;
    else
        System.out.prinln(i * (myFactorial(--i)));
}

การเรียกซ้ำมักจะมีประสิทธิภาพน้อยกว่าเนื่องจากต้องพุชและป๊อปการเรียกซ้ำดังนั้นการวนซ้ำจึงเร็วกว่า ในทางกลับกันเวอร์ชันที่เรียกซ้ำจะใช้ตัวแปรท้องถิ่นน้อยลงหรือไม่มีเลยซึ่งเป็นข้อดี


1

Factorial เป็นฟังก์ชันแยกที่เพิ่มขึ้นอย่างมากดังนั้นฉันคิดว่าการใช้ 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 ที่ไม่ได้ลงชื่อ




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);
}
}

0
public static int fact(int i){
    if(i==0)
       return 0;
    if(i>1){
       i = i * fact(--i);
    }

   return i;
}

1
ฉันคิดว่า OP กำลังถามว่ามีฟังก์ชันใน API หรือไม่ไม่ใช่วิธีการเขียน นอกจากนี้ 0! = 1 - คุณอาจต้องการอัปเดตรหัสของคุณเพื่อรวมกรณีดังกล่าว
SL Barth - คืนสถานะ Monica

ผลเสมอ 0
Tom Brito

0

เราจำเป็นต้องดำเนินการซ้ำ ๆ หากเราใช้งานแบบวนซ้ำจะทำให้เกิด StackOverflow หากอินพุตมีขนาดใหญ่มาก (เช่น 2 พันล้าน) และเราจำเป็นต้องใช้หมายเลขขนาดที่ไม่ถูกผูกไว้เช่น BigInteger เพื่อหลีกเลี่ยงการล้นทางคณิตศาสตร์เมื่อจำนวนแฟกทอเรียลมีขนาดใหญ่กว่าจำนวนสูงสุดของประเภทที่กำหนด (เช่น 2 พันล้านสำหรับ int) คุณสามารถใช้ 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;
}


0

ในขณะที่วนซ้ำ (สำหรับตัวเลขขนาดเล็ก)

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);
   }
}

0

ฉันได้รับสิ่งนี้จาก EDX ใช้มัน! เรียกว่าการเรียกซ้ำ

   public static int factorial(int n) {
    if (n == 1) {
        return 1;
    } else {
        return n * factorial(n-1);
    }
}

0

ด้วยการเรียกซ้ำ:

public static int factorial(int n)
{
    if(n == 1)
    {
        return 1;
    }               
    return n * factorial(n-1);
}

กับ while loop:

public static int factorial1(int n)
{
    int fact=1;
    while(n>=1)
    {
        fact=fact*n;
        n--;
    }
    return fact;
}

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];
 }

0

การใช้การเรียกซ้ำเป็นวิธีที่ง่ายที่สุด ถ้าเราต้องการหาแฟกทอเรียลของ N เราต้องพิจารณาสองกรณีที่ N = 1 และ N> 1 เนื่องจากในแฟกทอเรียลเราจะคูณ N, N-1, N-2 ,,,, จนถึง 1 ต่อไปถ้าเรา ไปที่ N = 0 เราจะได้ 0 สำหรับคำตอบ ในการหยุดแฟกทอเรียลถึงศูนย์จะใช้วิธีการวนซ้ำต่อไปนี้ ภายในฟังก์ชันแฟกทอเรียลในขณะที่ N> 1 ค่าที่ส่งกลับจะถูกคูณด้วยการเริ่มต้นอื่นของฟังก์ชันแฟกทอเรียล สิ่งนี้จะทำให้โค้ดเรียกซ้ำแฟกทอเรียล () จนกว่าจะถึง 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;
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.