30/09/2018, 20:08

Viết hàm tính s(n) = 1 + 1/2 + 1/3 + ... + 1/n bằng đệ quy nhưng bị lỗi lặp vô tận

Dưới đây là 1 bài tập mình tìm trên mạng và code thử, sao mình tính thì được nhưng khi compile thì nó bị lỗi, cửa số console vẫn hiện, vẫn nhập được nhưng Enter thì nó báo lỗi Has stopped working … gì ấy mình k nhớ lắm! Các bạn giỏi giúp mình nhé (đặc biệt là những bạn rành về đệ quy)!
Đề:

Và dưới đây là code mình làm ra nhưng bị lỗi khi run (vẫn compile được):

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <math.h>
#include <string.h>
int fraction(int n);
int main()
{
    int number;
   printf("Type a number: ");
    while ((scanf("%d", &number)) != EOF)
        printf("Result: %d
", fraction(number));
}
int fraction(int n)
{
    if (n == 1)
        return 1;
    return (1/n)+fraction(1/n-1);
}
Gió viết 22:24 ngày 30/09/2018

Khi n>1 thì fraction(1/n-1)=…+fraction(-1)
Chạy fraction(-1)= lại chạy fraction(1/(-1)-1)= fraction(0) sau bước này bị lỗi chia cho 0
Tính bị sa bị lặp do chạy về -oo

Người bí ẩn viết 22:22 ngày 30/09/2018

Mình vẫn chưa hiểu giải thích của bạn lắm Bạn có thể giải thích kỹ hơn xíu được không?

Sáng Béo viết 22:22 ngày 30/09/2018

fraction(1/n-1)

cái này là fraction(n-1) nhé

Mình vẫn chưa hiểu giải thích của bạn lắm Bạn có thể giải thích kỹ hơn xíu được không?

tức là bạn gọi đệ quy fraction(1/n-1)
do n>1 nên 1/n = 0 => 1/n - 1 sẽ = -1. rồi -1 này lại gọi trong phép đệ quy tiếp là 1/(-1) - 1 = -2, rồi phép đệ quy sau là -3 …
bạn gọi đệ quy nó sẽ bị lặp vô hạn.

Người bí ẩn viết 22:17 ngày 30/09/2018

cái này là fraction(n-1) nhé

Mình đã thử và kết quả đều trả về = 1 Không đúng nhé

Sáng Béo viết 22:17 ngày 30/09/2018

Mình đã thử và kết quả đều trả về = 1 Không đúng nhé

bạn phải ép kiểu và trả về float nhé.
số nguyên n>1 thì cứ 1/n nó sẽ thành 0, nên chỉ có 1/1 nó mới có giá trị là 1. => luôn là 1

#include <stdio.h>
#include <conio.h>

float fraction(int n);
int main()
{
    int number;
	printf("Type a number: ");
    while ((scanf("%d", &number)) != EOF)
        printf("Result: %.2f\n", fraction(number));
}
float fraction(int n)
{
    if (n == 1)
        return 1;
    return ((float) 1)/n + fraction(n-1);
}

có mấy thư viện không dùng đến mình bỏ đi rồi, chắc bạn dùng trong phần khác.

Người bí ẩn viết 22:15 ngày 30/09/2018

fraction(1/n-1);

À, chỗ này có chút lầm, mình sửa thành fraction(1/(n-1)); nhé, nhưng vẫn không chạy được :D?

Sáng Béo viết 22:23 ngày 30/09/2018

À, chỗ này có chút lầm, mình sửa thành fraction(1/(n-1)); nhé, nhưng vẫn không chạy được :D?

mình giải thích bên trên, bạn hiểu chưa?

Người bí ẩn viết 22:13 ngày 30/09/2018

À, được rồi, nhưng chưa hiểu lắm.

return ((float) 1)/n + fraction(n-1);

Bạn có thể giải thích cách hoạt động của lệnh này không? Cho float vào trực tiếp lệnh return cũng dc hả?

Sáng Béo viết 22:17 ngày 30/09/2018

Bạn có thể giải thích cách hoạt động của lệnh này không? Cho float vào trực tiếp lệnh return cũng dc hả?

cái (float) là ép kiểu float, nếu không ép kiểu thì 1/n sẽ trả về kết quả kiểu int do 1 và n đều là int. và do (1/n) là int nên khi chia nó sẽ lấy phần nguyên và bỏ phần thập phân. Vì vậy mình ép kiểu cho 1 thành kiểu float (chỉ cần 1 trong 2 thành phần tham gia phép tính có kiểu float) thì phép tính 1/n sẽ có giá trị mang kiểu float và phần thập phân sẽ được giữ lại.
Do chỉ ép kiểu cho 1 nên mình bọc (float) 1 trong cặp ngoặc…
Bạn chú ý là (float) 1/n với ((float) 1)/n không giống nhau đâu nhé.

À, chỗ này có chút lầm, mình sửa thành fraction(1/(n-1)); nhé, nhưng vẫn không chạy được :D?

không phải, lúc gọi hàm bạn chỉ cần truyền vào mẫu số thôi chứ không cần truyền cả phân số. lúc return nó sẽ tính phân số cho bạn (cái 1/n ấy).

Người bí ẩn viết 22:11 ngày 30/09/2018

À, có cách nào mà kết quả ở dạng phân số không nhỉ? Tức là hai phân số cộng lại ra 1 kết qua là phân số thay vì số thập phân ấy?

Sáng Béo viết 22:11 ngày 30/09/2018

cái này chắc bạn tạo lớp rồi overload operator +

Người bí ẩn viết 22:19 ngày 30/09/2018

Bạn nói thế thì mình chịu Không hiểu 100%

Sáng Béo viết 22:18 ngày 30/09/2018

Bạn nói thế thì mình chịu Không hiểu 100%

Bạn học OOP chưa?

Người bí ẩn viết 22:25 ngày 30/09/2018

OOP

À, dĩ nhiên là chưa?
Mà lập trình hướng đối tượng có quan trong không nhỉ? Nó nghĩa là gì?

Sáng Béo viết 22:10 ngày 30/09/2018

Mà lập trình hướng đối tượng có quan trong không nhỉ? Nó nghĩa là gì?

Tất nhiên là quan trọng rồi

Hoặc có thể vào ĐÂYđể tìm hiểu rõ hơn về principles of object oriented Đó là theo quan điểm hàn lâm. Nói dễ hiểu hơn Object oriented programming(OOP) hay Lập trình hướng đối tượng. Được phát triển từ những năm 2000 nhằm thay thế cho lập trình thủ tục như C. Giúp người lập trình quản lý phát triển và quản lý code dễ dàng hơn. Nhìn vào tên của nó bạn cũng có thể hình dung ra được. Ngôn ngữ lập trình này giải quyết các bài toán từ nhỏ đến lớn bằng cách quan sát và tưởng tượng những hành động,…
NhatTa viết 22:14 ngày 30/09/2018

@tucanhminh nếu chưa biết OOP có thể dùng struct in c để thay thế nha

        struct Fractions
        {
             int numerator, denominator;
        }

        Fractions Add2Fractions(Fractions p1, Fractions p2)
        {
            int T = p1.numerator * p2.denominator + p2.numerator * p1.denominator;
            int M = p1.denominator * p2.denominator;
            Fractions p;
            p.numerator = T;
            p.denominator = M;
            return p;
        }


        Fractions fraction(int n)
        {
            Fractions p1, p2;
            p1.numerator = 1;
            p1.denominator = 1;
            if (n == 1)
                return p1;
            p2.numerator = 1;
            p2.denominator = n;
            return Add2Fractions(p2, fraction(n - 1));
        }
Người bí ẩn viết 22:25 ngày 30/09/2018

Cảm ơn bạn nhe! Mặc dù mình không hiểu hết code của bạn

NhatTa viết 22:17 ngày 30/09/2018

Đầu tiên bạn tạo ra một struct Phân số với 2 thuộc tính tử và mẫu. Sau đó viết hàm cộng hai phân số với tham số truyển vào là 2 struct. Còn hàm đệ quy thì tương tự thôi. chek tại code c# nên hơi khó đọc
Bạn có thể tham khảo cách sử dụng struct ở đây or search struct in c là hiểu ngay
http://www.tutorialspoint.com/cprogramming/c_structures.htm

Người bí ẩn viết 22:13 ngày 30/09/2018

Khà khà, sau gần nửa năm mài miệt luyện công cực khổ, cuối cùng ta cũng đã hiểu struct và áp dụng cho bài này

Lương Quang Mạnh viết 22:18 ngày 30/09/2018

bài này cần gì struct nhỉ? (chưa học nên chả biết struct là cái gì cơ mà mình thì không cần nó).

#include <stdio.h>

double tong(int n) {
    if (n <= 1) return 1;
    return (double) 1/n + tong(n - 1);
}

int main() {
    /* whatever you put here, it will be run. */
}
Bài liên quan
0