Từ 1 tới 9 trên tổng số 9 kết quả

Đề tài: Tìm và in ra các số nguyên tố thỏa mãn đề bài bằng C, thuật toán của mình sai ở đâu?

  1. #1
    Ngày gia nhập
    01 2010
    Nơi ở
    Hà Nội
    Bài viết
    37

    Mặc định Tìm và in ra các số nguyên tố thỏa mãn đề bài bằng C, thuật toán của mình sai ở đâu?

    Mình mới học C ở trường, dc giao một bài tập về nhà với nội dung là
    Tìm tất cả các số nguyên tố trong đoạn [1,n] với n nhập từ bàn phím
    In các số nguyên tố này ra bàn phím thỏa mãn điều kiện mỗi dòng có soluong (nhập từ bàn phím) số nguyên tố, độ rộng của mỗi số nguyên tố bằng độ rộng của số nguyên tố lớn nhất trong đoạn [1,n] cộng thêm 1 (tức là nếu số lớn nhất có 3 chữ số thì độ rộng của tất cả các số khi in ra đều là 4, số có 1 chữ số thì thêm 3 dấu cách, 2 chữ số thì thêm 2 dấu cách....
    Mình có code C thế này
    C Code:
    1. #include <stdio.h>
    2. #include <math.h>
    3.  
    4. int main()
    5. {
    6.     int n, soluong, i=0, j=0, k=0, ntlonnhat=0, dorongi=0, doronglonnhat=0, t=0;
    7.  
    8.     printf("Nhap n : ");
    9.     scanf("%d", &n);
    10.  
    11.     printf("Nhap so luong so nguyen to trong 1 dong : ");
    12.     scanf("%d", &soluong);
    13.  
    14.     for (i = 2; i<=n; i++) //Tìm ra số nguyên tố lớn nhất trong đoạn [1;n]
    15.     {
    16.         int dem=0;
    17.         for (j=2; j<=sqrt(i); j++)
    18.         {
    19.             if (i % j == 0)
    20.                 dem = dem + 1;
    21.         }
    22.  
    23.         if (dem == 0)
    24.         {
    25.             if (i > ntlonnhat)
    26.             {
    27.                 ntlonnhat = i;
    28.             }
    29.         }
    30.     }
    31.  
    32.     while (ntlonnhat >= 1) //Tìm độ rộng lớn nhất, nó bằng độ dài của số nguyên tố lớn nhất
    33.         {
    34.             ntlonnhat = ntlonnhat / 10;
    35.             doronglonnhat = doronglonnhat + 1;
    36.         }
    37.  
    38.  
    39.     for (i = 2; i<=n; i++) //In ra các số nguyên tố với độ rộng thỏa mãn
    40.     {
    41.         int dem=0;
    42.         for (j=2; j<=sqrt(i); j++)
    43.         {
    44.             if (i % j == 0)
    45.                 dem = dem + 1;
    46.         }
    47.  
    48.         if (dem == 0)
    49.         {
    50.             printf("%d",i);
    51.             while (i>=1)
    52.             {
    53.                 i = i / 10;
    54.                 dorongi = dorongi + 1;
    55.             }
    56.             for (t=0; t<=(doronglonnhat-dorongi); t++)
    57.             {
    58.                 printf(" ");
    59.             }
    60.             k = k + 1;
    61.         }
    62.         if (k == soluong)
    63.             {
    64.                 k = 0;
    65.                 printf("\n");
    66.             }
    67.     }
    68.  
    69.     return 0;
    70. }

    Khi compile thì ko có lỗi cú pháp nên mình nghĩ là do lỗi thuật toán. Bạn nào biết giúp mình với dc không. Mình lần đầu post bài hỏi nên có gì thiếu sót trong việc trình bày lỗi các bạn nói mình sẽ bổ sung ngay

    Cảm ơn !
    Đã được chỉnh sửa lần cuối bởi piavg : 25-09-2011 lúc 05:50 PM.

  2. #2
    Ngày gia nhập
    07 2011
    Bài viết
    160

    Code của bạn không có cấu trúc và căn lề cũng tệ nên khó nhìn quá
    Mình xin phép chỉnh lại 1 số chỗ:
    C Code:
    1. #include <stdio.h>
    2. #include <math.h>
    3.  
    4. int nguyento(int n)
    5. {
    6.     int i, sqrt_n = 0.1 + sqrt(n);  /* Lưu lại cho đỡ phải tính nhiều lần. +0.1 cho chắc ăn vì convert số thực - số nguyên có thể phát sinh vấn đề */
    7.     if (n < 2) return 0;
    8.     for (i=2; i <= sqrt_n; ++i)
    9.         if (0 == n % i) return 0;
    10.     return 1;
    11. }
    12.  
    13. int main()
    14. {
    15.     int n, soluong, i=0, k=0, ntlonnhat=0, doronglonnhat=0;
    16.     char format[10] = "%2d";
    17.  
    18.     printf("Nhap n : ");
    19.     scanf("%d", &n);
    20.  
    21.     printf("Nhap so luong so nguyen to trong 1 dong : ");
    22.     scanf("%d", &soluong);
    23.  
    24.     for (i = 2; i<=n; i++)                  /* Tìm ra số nguyên tố lớn nhất trong đoạn [1;n] */
    25.         if (nguyento(i)) ntlonnhat = i;     /* i tăng dần nên không cần kiểm tra ntlonnhat > i */
    26.     for (doronglonnhat = 1; ntlonnhat >= 10; ntlonnhat /= 10) ++doronglonnhat;
    27.     format[1] = '1' + doronglonnhat;        /* chỉ đúng khi doronglonnhat <= 8, chắc vậy là đủ */
    28.  
    29.     for (i = 2; i<=n; i++)                  /* In ra các số nguyên tố với độ rộng thỏa mãn */
    30.     {
    31.         if (!nguyento(i)) continue;
    32.         printf(format, i);
    33.         if (++k % soluong == 0) printf("\n");
    34.     }
    35.  
    36.     return 0;
    37. }
    Đã được chỉnh sửa lần cuối bởi fbchicken : 22-09-2011 lúc 11:17 PM.

  3. #3
    Ngày gia nhập
    06 2011
    Bài viết
    5

    Code:
    #include <stdio.h>
    #include <math.h>
    
    int nguyento(int n)
    {
        int i, sqrt_n = 0.1 + sqrt(n);  /* Lưu lại cho đỡ phải tính nhiều lần. +0.1 cho chắc ăn vì convert số thực - số nguyên có thể phát sinh vấn đề */
        if (n < 2) return 0;
        for (i=2; i <= sqrt_n; ++i)
            if (0 == n % i) return 0;
        return 1;
    }
    Mình nghĩ chỗ này
    Code:
    int i, sqrt_n = 0.1 + sqrt(n)
    sqrt(n) + 0.1 luôn là kiểu float, mà gán sqrt_n là kiểu int = nó.

  4. #4
    Ngày gia nhập
    04 2010
    Bài viết
    1,534

    Khi tìm số lớn nhất trong một dãy số có thứ tự, ta tìm ngược từ đuôi. Số đàu tiên tìm được là số lớn nhất

    C Code:
    1.     for (i = n; i<=2; i--)                  /* Tìm ra số nguyên tố lớn nhất trong đoạn [1;n] */
    2.         if (nguyento(i)) { ntlonnhat = i; break; }     /* i đầu tiên cũng là lớn nhất */

    @piavg: cho biết sai ra sao? Kết quả ra sao và nếu đúng thì phải ra sao?

  5. #5
    Ngày gia nhập
    08 2011
    Nơi ở
    /pentest
    Bài viết
    44

    @jetmoon: chỗ bạn bảo sai thực ra không sai, vế phải là float sẽ bị ép kiểu ko tường mình sang kiểu nguyên, nghĩa là kiểu của giá trị biểu thức ở về phải phải bị ép kiểu về kiểu của biến ở về trái, cái này nằm trong chuẩn của C,C++ nên ko có gì ngạc nhiên, mà g/s bạn khai báo float sqrt_n = 0.1 + sqrt(n) thì tý nữa xuống vòng for bạn lại phải ép kiểu sqrt_n về int để so sánh với i nên khai báo như trên thì đỡ đi một n lần ép kiểu từ thực sang nguyên và chắc chắn tối ưu hơn.

    Tìm số ngto lớn nhất thì làm như VoTichSu sẽ tối ưu hơn.
    Đã được chỉnh sửa lần cuối bởi meterpreter : 24-09-2011 lúc 12:13 PM. Lý do: @jetmoon
    We are oft to blame in this...'Tis too much proved.
    - That with devotion's visage and pious action we do sugar o'er the devil himself.

  6. #6
    Ngày gia nhập
    01 2010
    Nơi ở
    Hà Nội
    Bài viết
    37

    Mặc định Tìm và in ra các số nguyên tố thỏa mãn đề bài bằng C, thuật toán của mình sai ở đâu?

    Trích dẫn Nguyên bản được gửi bởi VoTichSu Xem bài viết

    @piavg: cho biết sai ra sao? Kết quả ra sao và nếu đúng thì phải ra sao?
    Khi mình cho chạy cái code của mình thì hiện ra một hàng 10 số 1 cứ chạy liên tục không dừng thôi. Mà code trên mình copy nguyên từ editor của mình vào nên nếu bạn copy y nguyên cái đó vào editor của bạn có lẽ là compile dc ngay, mình thì mình đang muốn hỏi tại sao nó sai mà

    Cho mình hỏi một số chỗ mình chưa hiểu (mình viết luôn ở code):

    Trích dẫn Nguyên bản được gửi bởi fbchicken Xem bài viết
    Code của bạn không có cấu trúc và căn lề cũng tệ nên khó nhìn quá
    Mình xin phép chỉnh lại 1 số chỗ:
    C Code:
    1. #include <stdio.h>
    2. #include <math.h>
    3.  
    4. int nguyento(int n)
    5. {
    6.     int i, sqrt_n = 0.1 + sqrt(n);  /* Lưu lại cho đỡ phải tính nhiều lần. +0.1 cho chắc ăn vì convert số thực - số nguyên có thể phát sinh vấn đề */
    7.     if (n < 2) return 0;
    8.     for (i=2; i <= sqrt_n; ++i) ([COLOR="Red"]Chỗ này có thể là i++ ko, nếu có thể thì ++i sẽ khác gì[/COLOR])
    9.         if (0 == n % i) return 0;
    10.     return 1;
    11. }
    12.  
    13. int main()
    14. {
    15.     int n, soluong, i=0, k=0, ntlonnhat=0, doronglonnhat=0;
    16.     char format[10] = "%2d"; ([COLOR="Red"]biên char này làm công việc gì[/COLOR])
    17.  
    18.     printf("Nhap n : ");
    19.     scanf("%d", &n);
    20.  
    21.     printf("Nhap so luong so nguyen to trong 1 dong : ");
    22.     scanf("%d", &soluong);
    23.  
    24.     for (i = 2; i<=n; i++)                  /* Tìm ra số nguyên tố lớn nhất trong đoạn [1;n] */
    25.         if (nguyento(i)) ntlonnhat = i;     /* i tăng dần nên không cần kiểm tra ntlonnhat > i */
    26.     for (doronglonnhat = 1; ntlonnhat >= 10; ntlonnhat /= 10) ++doronglonnhat;
    27.     format[1] = '1' + doronglonnhat; ([COLOR="Red"]mình cũng chưa hiểu chỗ này[/COLOR])     /* chỉ đúng khi doronglonnhat <= 8, chắc vậy là đủ */
    28.  
    29.     for (i = 2; i<=n; i++)                  /* In ra các số nguyên tố với độ rộng thỏa mãn */
    30.     {
    31.         if (!nguyento(i)) continue; ([COLOR="Red"]sao lại có dấu ! ở trước nguyento(i), và lệnh continue để làm gì[/COLOR])
    32.         printf(format, i);
    33.         if (++k % soluong == 0) printf("\n");
    34.     }
    35.  
    36.     return 0;
    37. }
    Cảm ơn bạn! (À cho mình hỏi luôn làm sao add code để nó hiện màu như trong editor như của bạn vậy?)
    Đã được chỉnh sửa lần cuối bởi kitti : 24-09-2011 lúc 08:41 PM. Lý do: làm liền các bài viết spam
    Cám ơn mỗi sớm mai thức dậy
    Ta có thêm ngày nữa để yêu thương

  7. #7
    Ngày gia nhập
    07 2011
    Bài viết
    160

    Trích dẫn Nguyên bản được gửi bởi piavg Xem bài viết
    Cho mình hỏi một số chỗ mình chưa hiểu (mình viết luôn ở code):



    Cảm ơn bạn! (À cho mình hỏi luôn làm sao add code để nó hiện màu như trong editor như của bạn vậy?)
    1. Để code có màu thì bạn dùng thẻ code như bình thường, xong thêm viết thêm =C hoặc =C++ vào ([ CODE=C ] , không có dấu cách trong ngoặc vuông)
    2. Tìm số nguyên tố lớn nhất thì for ngược lại như VoTichSu nói là chuẩn rồi. Lúc đó mình sửa luôn trên code của bạn nên chưa để ý tối ưu đoạn đó.
    3. char format[10]="%2d": Bạn có để ý mình dùng printf(format, i) không? Nếu format không bị thay đổi thì sẽ là tương đương printf("%2d", i). Nhưng lệnh format[1] = '1' + doronglonnhat đã chỉnh cái số 2 thành số tương ứng với độ rộng lớn nhất + 1. Ví dụ doronglonnhat là 3 thì printf(format, i) sẽ tương đương với printf("%4d", i). Vì '1' + 3 = '4'
    4. Lệnh continue sẽ nhảy đến thực hiện tiếp lần lặp tiếp theo. Dấu ! là NOT. Tức là nếu i không phải số nguyên tố thì sẽ bỏ qua không thực hiện 2 dòng code ở bên dưới. Viết:
    C Code:
    1.     for (i = 2; i<=n; i++)                  /* In ra các số nguyên tố với độ rộng thỏa mãn */
    2.     {
    3.         if (!nguyento(i)) continue;
    4.         printf(format, i);
    5.         if (++k % soluong == 0) printf("\n");
    6.     }
    tương đương với
    C Code:
    1.     for (i = 2; i<=n; i++)                  /* In ra các số nguyên tố với độ rộng thỏa mãn */
    2.     {
    3.         if (nguyento(i)) {
    4.                 printf(format, i);
    5.                 if (++k % soluong == 0) printf("\n");
    6.         }
    7.     }
    nhưng với cá nhân mình thì cách viết continue dễ nhìn hơn vì 2 lý do:
    - 1: Mình nhìn là biết ngay nó sẽ nhảy đến lần lặp kế tiếp, không thực hiện gì khác trong lần lặp đó. Với cách sau, nếu code dài mình còn phải cuộn xuống kiểm tra xem bên dưới block của if có gì nữa không.
    - 2: Mỗi block con đều phải căn lề vào trong 1 tab. Mà khi quá nhiều block lồng nhau, lùi vào sâu quá sẽ khó nhìn. Nên mình hạn chế block con khi có thể.

    ---------------
    5. Code của bạn bị lặp vô hạn vì trong vòng lặp for i để in ra, bạn lại thay đổi chính biến i. Sửa lại bằng cách gán 1 biến i2 = i rồi tính toán trên biến i2 là được. (mới xem mỗi chỗ đó, còn có lỗi khác không thì ko rõ )
    Đã được chỉnh sửa lần cuối bởi fbchicken : 24-09-2011 lúc 11:15 PM.

  8. #8
    Ngày gia nhập
    01 2010
    Nơi ở
    Hà Nội
    Bài viết
    37

    Trích dẫn Nguyên bản được gửi bởi fbchicken Xem bài viết
    1. Để code có màu thì bạn dùng thẻ code như bình thường, xong thêm viết thêm =C hoặc =C++ vào ([ CODE=C ] , không có dấu cách trong ngoặc vuông)
    2. Tìm số nguyên tố lớn nhất thì for ngược lại như VoTichSu nói là chuẩn rồi. Lúc đó mình sửa luôn trên code của bạn nên chưa để ý tối ưu đoạn đó.
    3. char format[10]="%2d": Bạn có để ý mình dùng printf(format, i) không? Nếu format không bị thay đổi thì sẽ là tương đương printf("%2d", i). Nhưng lệnh format[1] = '1' + doronglonnhat đã chỉnh cái số 2 thành số tương ứng với độ rộng lớn nhất + 1. Ví dụ doronglonnhat là 3 thì printf(format, i) sẽ tương đương với printf("%4d", i). Vì '1' + 3 = '4'
    4. Lệnh continue sẽ nhảy đến thực hiện tiếp lần lặp tiếp theo. Dấu ! là NOT. Tức là nếu i không phải số nguyên tố thì sẽ bỏ qua không thực hiện 2 dòng code ở bên dưới. Viết:
    C Code:
    1.     for (i = 2; i<=n; i++)                  /* In ra các số nguyên tố với độ rộng thỏa mãn */
    2.     {
    3.         if (!nguyento(i)) continue;
    4.         printf(format, i);
    5.         if (++k % soluong == 0) printf("\n");
    6.     }
    tương đương với
    C Code:
    1.     for (i = 2; i<=n; i++)                  /* In ra các số nguyên tố với độ rộng thỏa mãn */
    2.     {
    3.         if (nguyento(i)) {
    4.                 printf(format, i);
    5.                 if (++k % soluong == 0) printf("\n");
    6.         }
    7.     }
    nhưng với cá nhân mình thì cách viết continue dễ nhìn hơn vì 2 lý do:
    - 1: Mình nhìn là biết ngay nó sẽ nhảy đến lần lặp kế tiếp, không thực hiện gì khác trong lần lặp đó. Với cách sau, nếu code dài mình còn phải cuộn xuống kiểm tra xem bên dưới block của if có gì nữa không.
    - 2: Mỗi block con đều phải căn lề vào trong 1 tab. Mà khi quá nhiều block lồng nhau, lùi vào sâu quá sẽ khó nhìn. Nên mình hạn chế block con khi có thể.

    ---------------
    5. Code của bạn bị lặp vô hạn vì trong vòng lặp for i để in ra, bạn lại thay đổi chính biến i. Sửa lại bằng cách gán 1 biến i2 = i rồi tính toán trên biến i2 là được. (mới xem mỗi chỗ đó, còn có lỗi khác không thì ko rõ )
    Đúng rồi bạn ạ, trước vòng lặp i đặt lại i2=i rồi cho thay đổi giá trị của i2 là ra kết quả. Cảm ơn bạn nhé
    Cám ơn mỗi sớm mai thức dậy
    Ta có thêm ngày nữa để yêu thương

  9. #9
    Ngày gia nhập
    09 2011
    Bài viết
    5

    code nên viết có tổ chức chút nhé.linh tinh kinh.
    fbchicken viết đc roài.

Các đề tài tương tự

  1. Thuật toán tìm số nguyên tố?
    Gửi bởi comeonbaby trong diễn đàn Thắc mắc CTDL & Giải thuật
    Trả lời: 92
    Bài viết cuối: 22-03-2017, 08:39 PM
  2. Bài tập C giải thuật nhập vào số nguyên n in ra n số nguyên tố đầu tiên?
    Gửi bởi LTC trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 48
    Bài viết cuối: 25-04-2013, 07:40 PM
  3. thuật toán số nguyên tố????
    Gửi bởi anhtbok trong diễn đàn Nhập môn lập trình C/C++
    Trả lời: 9
    Bài viết cuối: 30-03-2012, 10:33 AM
  4. Lập trình C xin code cài đặt thuật toán sàng nguyên tố để liệt kê các số nguyên tố 2->480000
    Gửi bởi ngocdung_088 trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 23
    Bài viết cuối: 06-12-2010, 11:53 PM
  5. Hàng đợi | Thuật toán in đảo số nguyên n
    Gửi bởi hoangchauhamy trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 2
    Bài viết cuối: 18-05-2009, 08:37 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn