[Lập trình C] Extra long factorials - Giai thừa siêu lớn

Saturday, December 26, 2020
Edit this post


Giai thừa của một số n > 20 thậm chí không thể được lưu trữ trong một biến kiểu long 64-bit. Với những tính toán như vậy, chúng ta cần phải sử dụng Big Integers. Các ngôn ngữ lập trình như Java, Python, Ruby v.v... có thể giúp chúng ta handle Big Integers một cách tương đối dễ dàng. Tuy vậy, đối với C/C++ thì chúng ta cần phải tự xử lý những giá trị lớn như vậy. Đây là một bài tập mà tôi vừa mới làm trên HackerRank, thấy hay nên chia sẻ lại với mọi người.

Yêu cầu:

Nhập vào một số nguyên n sao cho 20 <= n <= 100. Hãy tính và in ra giai thừa của n dựa vào công thức bên dưới.


Ví dụ giai thừa của 30 được tính như sau: 30! = 30 * 29 * 28 * 27 * ... * 3 * 2 * 1 = 265252859812191058636308480000000 (kết quả là một số có tổng cộng 33 chữ số).

Gợi ý:

Tôi sẽ dùng một mảng a có độ lớn khoảng 1000 phần tử với mỗi ô nhớ của mảng sẽ lưu trữ 1 số duy nhất của kết quả cho mỗi bước tính. Ví dụ khi tính 10! thì qua từng bước tính mảng a trông sẽ như sau:


Cách giải này không phải do tôi nghĩ ra mà được tôi tham khảo ở link sau: Extra Long Factorials in C. Để hiểu được một cách cặn kẽ, tôi khuyên bạn nên lấy giấy bút và thử debug lại từng bước lặp bằng tay, khi đó bạn sẽ hiểu rất rõ.

Cài đặt:

Như trong code bên dưới, biến number dùng để duyệt lần lượt các giá trị từ 2 cho đến n. Biến len dùng để chứa độ dài hiện tại của dãy kết quả. Trong bài tập này tôi sử dụng mảng có độ dài cố định 1000 nhưng để tối ưu hơn, các bạn có thể cải tiến sử dụng mảng cấp phát động. Biến carry dùng để chứa số dư. Ví dụ, giả sử tôi đang duyệt ô nhớ có giá trị = 2 và number = 7. Khi đó 2 * 7 = 14 > 10. Tôi sẽ cập nhật giá trị ô nhớ hiện tại = 14 % 10 (lấy dư). Còn biến carry = 14 / 10 = 4. Phần dư carry này sẽ được tôi mang qua tính toán ở ô nhớ tiếp theo.

#include <stdio.h>

void extraLongFactorials(int n) {
    int a[1000] = {0};
    a[0] = 1;
    int number = 2;
    int len = 1;
    
    while (number <= n) {
        int carry = 0;
        int i = 0;
        
        while (i < len) {
            a[i] *= number;
            a[i] += carry;
            carry = a[i] / 10;
            a[i] %= 10;
            i++;
        }
        
        while (carry != 0) {
            a[len] = carry % 10;
            carry /= 10;
            len++;
        }
        
        number++;
    }
    
    len--;
    while(len >=0) printf("%d", a[len--]);
}

int main()
{
    int n;
    printf("n=");
    scanf("%d", &n);
    extraLongFactorials(n);
    return 0;
}

.
Xin vui lòng chờ đợi
Dữ liệu bài viết đang được tải về

💻Nhận dạy online 1 kèm 1 Automation Test từ cơ bản tới nâng cao (From Zero to Hero) 😁😁😁
Lộ trình gồm 3 phần:
1) Kỹ thuật lập trình và tư duy lập trình cơ bản
2) Nhập môn kiểm thử (Manual Test)
3) Kiểm thử tự động (Automation Test) + Chuẩn bị cho phỏng vấn
* Lộ trình chi tiết: Xem tại đây

🎓Đối tượng người học:
- Những bạn bị mất gốc căn bản môn lập trình.
- Những bạn muốn theo con đường kiểm thử (testing), đặc biệt là kiểm thử tự động (Automation Test).

🦘Người giảng dạy:
- Mình sẽ là người trực tiếp hướng dẫn.
- Nếu là các vấn đề ngoài chuyên môn hoặc sở trường, mình sẽ nhờ các anh chị em khác cũng làm trong ngành.

🤓Giới thiệu:
- Mình đã có hơn 10 năm kinh nghiệm làm IT ở cả trong và ngoài nước. Trong đó 3 năm đầu là làm lập trình viên Java, sau đó bén duyên với mảng Automation Test và theo nghề tới tận bây giờ. Mình được đào tạo chính quy về IT từ một trường Đại học danh tiếng ở TP.HCM (hệ kỹ sư 4 năm rưỡi), có chứng chỉ ISTQB, có thể giao tiếp tốt bằng tiếng Anh và có kinh nghiệm làm việc thực tế ở cả 2 mảng Outsource và Product. Title chính thức của mình là QA Automation Engineer, tuy nhiên, mình vẫn làm những dự án cá nhân chuyên về lập trình ứng dụng như Học Tiếng Anh StreamlineSách Nhạc. Mình là người có thái độ làm việc chuyên nghiệp, chăm chỉ và luôn nhiệt tình trong công việc.

💵Chi phí và hình thức thanh toán:
- Các bạn vui lòng liên hệ qua email songtoigianvn@gmail.com (email, chat, hoặc call) để book nội dung và khung giờ học (từ 8h tối trở đi).
- Mức phí: 150.000đ/buổi, mỗi buổi 60 phút.
- Lộ trình From Zero to Hero: 4.350.000đ (29 buổi).
- Bạn có thể học riêng và đóng tiền theo từng phần nếu muốn.
- Có thể học trước 1-2 buổi trước khi quyết định đi full lộ trình hoặc từng phần.
- Thanh toán qua Momo, chuyển khoản v.v...
BÌNH LUẬN
© Copyright by CUỘC SỐNG TỐI GIẢN
Loading...