PDA

View Full Version : trong C sao tính được giai thừa (x!)



siegetank
17-03-2007, 16:52
em mới học C được ít lâu, có bài toán vòng lặp yêu cầu tính 1 biểu thức trong đó có giai thừa, nhưng đánh dấu vào thì lại ko chạy (VD:3!),không biết trong C làm sao để tính được giai thừa nhỉ.

tienthanh_tn
17-03-2007, 20:37
Mình không biết trong thư viện của C có hàm tính giai thừa không (toán tử ! như bạn viết là toán tử NOT chứ không phải giai thừa đâu).
Để tính được giai thừa của một số nguyên thì bạn có thể viết 1 hàm tính giai thừa (đệ quy hoặc vòng lặp), đây cũng là một bài toán cơ sở khi học C/C++ mà.
Bạn cần chú ý là khi dùng biến lưu kết quả là kiểu số nguyên thì chỉ có thể tính giai thừa cho 1 số nguyên tương đối nhỏ. Nếu số lớn một chút là gặp lỗi tràn số ngay (dù khi kết quả lưu vào biến kiểu unsigned long). Khi cần tính cho số khá lớn thì phải dùng biến lưu kết quả kiểu float, tốt nhất là double để lưu kết quả. Khi xuất kết quả dùng định dạng "%.0lf" (không hiển thị phần thập phân).

siegetank
17-03-2007, 22:06
viết chương trình riêng để tính giai thừa thì ok, nhưng cái chính là trong một bài toán khác, lại phải lồng chương trình tính giai thừa đó vào thì mình ko rõ.
VD như bài sau trong sách kĩ thuật lập trình của Phạm Văn ất:

tính e^x theo công thức: e^x=1+ x^1/1! + x^2/2!+....., dừng lặp khi x^n/n! < k (k nhập từ bàn phím)

dmtmufc
17-03-2007, 22:41
thế thì dùng đoạn mã này:
n=1;y=y+x/n;
while ((x/n)>=k) do
{
n=n*(n+1); x=x*x; y=y+(x/n);
}

dmtmufc
17-03-2007, 22:42
thế thì dùng đoạn mã này:
n=1;y=y+x/n;
while ((x/n)>=k) do
{
n=n*(n+1); x=x*x; y=y+(x/n);
}

dmtmufc
17-03-2007, 22:44
thế thì dùng đoạn mã này:
n=1;y=y+x/n;
while ((x/n)>=k)
{
n=n*(n+1); x=x*x; y=y+(x/n);
}

truongngocdai
18-03-2007, 11:05
dmtmufc spam bài 2 lần (Cảnh cáo)

Alien
18-03-2007, 11:17
Bạn cần chú ý là khi dùng biến lưu kết quả là kiểu số nguyên thì chỉ có thể tính giai thừa cho 1 số nguyên tương đối nhỏ. Nếu số lớn một chút là gặp lỗi tràn số ngay (dù khi kết quả lưu vào biến kiểu unsigned long). Khi cần tính cho số khá lớn thì phải dùng biến lưu kết quả kiểu float, tốt nhất là double để lưu kết quả. Khi xuất kết quả dùng định dạng "%.0lf" (không hiển thị phần thập phân).

Bạn không nên dùng kiểu double để hiển thị kết quả số nguyên, sẽ không chính xác, tốt nhất là unsigned long.

tienthanh_tn
18-03-2007, 19:40
Bạn không nên dùng kiểu double để hiển thị kết quả số nguyên, sẽ không chính xác, tốt nhất là unsigned long
Nhưng như mình đã nói ở trên, dùng unsigned long thì không thể lưu được kết quả tính giai thừa của một số khá lớn. Bởi vì trong C, số kiểu LONG chỉ có 32 bit, số nguyên không dấu lớn nhất có thể lưu là 2^32-1 = 4294967295 (<14!).
Khi lập trình trong windows thì có hỗ trợ số nguyên 64 bit=> có thể áp dụng tính giai thừa cho số lớn.
Còn về sai số trong kiểu số thực thì có thể yên tâm về độ chính xác của nó, sai số (tất nhiên phải có do cách lưu dữ liệu) rất nhỏ, thực sự không ảnh hưởng nhiều đến kết quả phép toán đơn giản. Mình nghĩ vậy, nếu không đúng thì mong các bạn góp ý!

Vinhie47
18-03-2007, 23:19
Muốn tính giai thừa cho số lớn chỉ có cách dùng mảng kí tự(nhưng hình như không đúng chủ đề thì phải :D)

Alien
19-03-2007, 01:02
Chắc phải vây. Số nguyên 64 bit cũng chỉ tính được 20!. Nếu là C# có decimal 128 bit, VB có kiểu Currency số rất lớn, còn C++ hình như lớn nhất chỉ có long double 80 bit thì phải.

Còn về sai số trong kiểu số thực thì có thể yên tâm về độ chính xác của nó, sai số (tất nhiên phải có do cách lưu dữ liệu) rất nhỏ, thực sự không ảnh hưởng nhiều đến kết quả phép toán đơn giản. Mình nghĩ vậy, nếu không đúng thì mong các bạn góp ý!

Theo mình nhớ thì kiểu double thể hiện tới 10 mũ mấy trăm (không biết có nhớ đúng không), trong khi nó chỉ có 16 tỉ tỉ giá trị. Vậy sai biệt có thể lên đến hàng triệu, thậm chí hàng tỉ nếu tính số lớn. Tuy nhiên so với kết quả hàng chục số không thì vẫn rất nhỏ. Nếu tính toán không yêu cầu chính xác tuyệt đối thì có thể dùng double.

mokona
24-04-2007, 11:54
Dùng đệ qui giải là nhanh nhất
int giaithua(unsigned int n)
{
if ((n==0)||(n==1)) return 1;
return giaithua(n-1)*n;
}
trong hàm main thì dùng vòng lặp kiểm soát n dừng lại như bạn nói.

lyhuyen_248
25-05-2007, 10:48
Thu bai nay xem
/*Tinh giai thua */
/* Cac khai bao tien xu ly */
#include<stdio.h>
#include<conio.h>
#include<math.h>

/* Ham main */
main()
{
// Khai bao bien
int n,i;
long int intGT;

do
{ clrscr();

// Cac lenh dieu khien
printf("\n\t Tinh giai thua ");
printf("\n\r Nhap n= ");scanf("%d",&n);
if(n<0)
{printf("\n Nhap sai "); }
else if(n>=0)
{
intGT=1;

for(i=1;i<=n;i++)
{
intGT*=i ;
}
printf("\n Ket qua la %d!= %ld",n,intGT);
}

getch();
printf("\n\n Tiep tuc Y/N: ");


}while(toupper(getch())!='N');
return 0;
}

tmay30
25-05-2007, 14:26
bài viết của bạn cũng rất hay !
mình hỏi bạn một câu này được không (ko riêng lyhuyen, nếu ai làm được vui lòng chỉ cho).
vẫn biết bài toán THÁP HÀ NỘI là chúng ta phải dùng cả đồ họa trong C để nhìn lời giải cho rõ ràng .thầy giáo mình nói là không cần dùng đồ họa để giải bài đó, vậy nếu thế thì khi nhập vào số đĩa và máy chạy thì sau đó chúng ta sẽ nhận được gì: có phải là số lần đĩa chạy hay không. xin giải dùm tôi nha.

thangkho0909
15-12-2010, 18:46
đây là đoạn code đơn giản của mình mong mọi người góp ý nha:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
class luythua
{
int luy;
int nduthua=1;
int duthua=1;
int luot=1;

public void liu()
{
Console.WriteLine("Nhap vao number :");
luy = Convert.ToInt32(Console.ReadLine());
while (luot++ <= luy)
{
duthua = duthua * nduthua;

nduthua++;
}
Console.WriteLine("=" + duthua);


}
}
class Program
{
static void Main(string[] args)
{
luythua l = new luythua();
l.liu();
}
}
}

anhthao10
21-02-2011, 21:55
Thu bai nay xem
/*Tinh giai thua */
/* Cac khai bao tien xu ly */
#include<stdio.h>
#include<conio.h>
#include<math.h>

/* Ham main */
main()
{
// Khai bao bien
int n,i;
long int intGT;

do
{ clrscr();

// Cac lenh dieu khien
printf("\n\t Tinh giai thua ");
printf("\n\r Nhap n= ");scanf("%d",&n);
if(n<0)
{printf("\n Nhap sai "); }
else if(n>=0)
{
intGT=1;

for(i=1;i<=n;i++)
{
intGT*=i ;
}
printf("\n Ket qua la %d!= %ld",n,intGT);
}

getch();
printf("\n\n Tiep tuc Y/N: ");


}while(toupper(getch())!='N');
return 0;
}

các bạn nói xem
bài trên chỉ tính đến 12! là đúng
lớn hơn ko đúng
khai báo như nào để tính được những số lớn hơn ?

thehiep8x
21-02-2011, 22:59
while(x<1) printf("nhap lai");
gt=1;
for(int i=1;i<x;i++)
gt*=i
->gt
ban chay thu doan code nay xem,nho lhai bao thu dien với lại khai báo bien luon nhen ở dây minh chỉ viết công thức thui

[=========> Bổ sung bài viết <=========]

for(int i=1;i<=n;i++) sua lai dùm mình nhầm

Than Dieu
23-02-2011, 09:46
Vấn đề này được giải quyết lâu rồi.

Nếu bạn nào quan tâm đến tính giai thừa có thể tham khảo link sau:
Giai thừa số nhỏ, số lớn, số cực lớn, kèm theo các trao đổi và thuật giải

Tính giai thừa tổng hợp (http://forums.congdongcviet.com/showthread.php?t=41154)

Tính giai thừa với số lớn (http://forums.congdongcviet.com/showthread.php?t=1540)

Rất mong bài viết của mình giúp ích cho các bạn!

doanquyit
24-02-2011, 09:59
chúng ta dùng hàm đệ quy là ok
#include<stdio.h>

int giaithua( int n){
if(n==0) return 1;
else return n*giaithua(n-1)

}
int main(){
int n;
cout<<"nhap n = "; cin >>n;
cout<<"n! = "<<giaithua(n);
system("pause");
return 0;
}