Hiện mình mới học lập trình tại đại học, sắp thi nhưng thầy mình ra đề toàn với khoảng số lớn, nếu nhập số nhỏ thì không sao nhưng nếu bỏ số lớn vào toàn bị tính sai (vd: sin(40), 1000!,…). Mình có đọc vài bài viết về cách lập trình trước để nếu bị tràn số thì vào main() vẫn tính được kết quả nhưng phần khai báo và hàm con lại quá dài mà thi thì không dùng được. Có ai chỉ mình phương pháp nào để tính với số lớn được không? Làm ra đúng trường hợp sô nhỏ chỉ được 50% điểm help mình với…
Phương pháp lập trình với số lớn
Dùng chuỗi để lưu số. Từ lúc nhỏ, được dạy tính các phép tính + - * /
thế nào thì thực hiện y như vậy.
mình vừa học chuỗi nên chưa hiểu rõ cách làm cho lắm, vd như để lưu giá trị của 1000! thì dùng cách nào vậy bạn, sau đó nếu muốn đếm có bao nhiêu số 0 trong khai triển 1000! thì nếu như (cách mình tự nghĩ) muốn chia rồi gán vào mảng lại thì làm sao với ạ, người mới học có vài tháng chưa thực hành được nhiều mà thầy cho toàn bài khó :(((
1000!
là phép nhân (*
) đấy. 1*2*3*...*1000
.
Đến đó thì cỡ khoảng vài ngàn đến chục ngàn số thôi.
Khai báo mảng to to sẵn luôn!
Sau đó cứ làm như thời tiểu học.
Riêng bài này thì có mẹo đấy
sin(40)
: các hàm lượng giác là hàm tuần hoàn mà
à bạn cho mình thêm cái này đc ko, thầy mình có cái tật là đề bảo số nguyên mà ổng nhập vào số thực mà vẫn ra kq là tạch, có cách nào kiểm tra số nhập vào là số thực mà báo nhập sai ko bạn? cách mình nghĩ ra là khai báo float sẵn rồi dùng if(n-int(n)!=0) thì báo sai rồi printf("%0.0f",n) để chỉ hiển thị phần nguyên mà ko biết đc ko nữa…
Mình khai báo int n;
là được một nửa,
scanf
có giá trị trả về là nửa còn lại.
Về sin thì nó có tính tuần hoàn.
VD: sin 0 = sin 360 = sin 720 đều là 0
Cho nên chỉ cần lấy mod cho 360 là đủ rồi
Về 1000! thì chuyển sang chuỗi và tính toán dựa trên chuỗi đó…
nhưng sao mình khai báo int n, vd dùng n=n-1 thì nhập vào 2.2 vẫn ra 1 do chương trình vẫn lấy phần nguyên nên toang chỗ đó đó bạn :////
vậy nếu h mình khai triển sin theo maclauran, viết chương trình dùng hàm để tính từng phần là (-1)^n.x^(2n+1)/(2n+1)! thì return cái đó mod cho 2*pi đúng ko bạn?
bạn nhập vào 2.2
lúc này n của bạn là 2 do nó chỉ nhận phần nguyên
muốn nhận 2.2 thì phải khai báo là float, double… kiểu số thực nha
trước khi bạn khải triển đẳng thức thì mod cho 180 hoặc pi là đủ rồi
nãy mình nói dư vì sin 0 = sin 180 = sin 360 = 0
vd bạn nhập 360 => mod cho 180 => 0
chạy đẳng thức thì kq = 0
nhập 450 => mod 180 => 90
=> sin 450 = sin 90 = 1
khi đó triển khai đẳng thức cũng nhanh hơn
cái này mình có thử dùng nhưng float thì ko mod đc, mà mình đổi qua độ rồi sang kiểu int để mod, sau đó lại chuyển về kiểu float để tính nhưng kq vẫn sai, mà bài này chỉ nhập toàn số thực để kiểm tra kq ko, bạn giúp mình chỗ mod với :(((
theo tôi thấy căn bản ở đây là phải dùng dữ liệu dạng cấu trúc biểu diễn lại vì hình như c không cung cấp thư viện kiểu BigInteger chắc chỉ đến long thôi:
bạn cấu trúc lại chung cho các số là xong. ví dụ như 2 tỷ là giới hạn của 1 số, thì cắt đôi nó thành 2 biến a và b, a max = 1 tỷ, b max = 1 tỷ, rồi viết thêm method +,- * / hợp lý cho 2 số đấy là xong, kiểu như b tràn tỷ rồi thì nhớ vào a ấy như phép toán có nhớ. còn lúc sinh ra phép toán thì viết hàm toString bắn về số dạng a tỷ tỷ b tỷ là done, tỷ là chuỗi mấy số 0 thôi.
Nói chung giải mấy bài số lớn này mình thấy nó dựa trên tiền đề lý thuyết chuyển từ cấu trúc hệ 10 sang các hệ số lớn hơn như 16, 32 có khi còn 64 … để ra cách biểu diễn ra chuỗi ngắn hơn =)) mà có hẳn 1 dự an Euler chuyên giải bài tập tính toán với số lớn