Vấn đề tràn số lớn

admin - 01/03/2023

Vấn đề tràn số lớn

Một số trường hợp đề bài cho số lớn, những kiểu dữ liệu thông thường như int (từ - 231 đến 231, khoảng 9 chữ số) bị tràn số, các em chú ý sử dụng kiểu long long (từ -263 đến 263, khoảng 18 chữ số) để thay thế nhé.

Ví dụ 1: Chiều dài 2 cạnh a, b của hình chữ nhật đề bài cho <= 106, có thể sử dụng kiểu int. Tuy nhiên nếu tính diện tích thì giá trị có thể lên đến 1012, khi đó phải ép kiểu sang kiểu long long.

Ví dụ 2. Cho hai số nguyên a và b, hãy tính tổng a+b và in kết quả ra màn hình.

Chương trình được viết như sau:

#include<iostream>
using namespace std;
int main()
{int a, b;
   cin>>a>>b;
   cout<<a+b;
   return 0;
}

     Khi chạy chương trình trên nếu ta nhập a=2000000000;  b=2000000000 thì kết quả in ra tổng là bao nhiêu?

Đa số sẽ trả lời là 4000000000 nhưng đây không phải là kết quả của của chương trình tạo ra, kết quả chạy chương trình sẽ in ra số âm.

2000000000

2000000000

-294967296

Process returned 0 (0x0)   execution time : 19.802 s

Press any key to continue.

Đây chính là hiện tượng bị tràn số vì kiểu int có giới hạn lớn nhất là 231-1 (khoảng 2.1*109). Kiểu như có 1 cái cốc đựng được 300 ml nước: lần 1 ta rót vào 200 ml, lần 2 ta rót thêm vào 200ml thì cốc chỉ chứa thêm được 100ml còn lại sẽ bị chảy ra ngoài.

 

Để giải quyết trường hợp này, ta có các cách giải quyết sau:

+ Khai báo kiểu dữ liệu của lớn hơn: chẳng hạn long long a, b,

+ Ép kiểu dữ liệu: pháp: (tên kiểu) (biến hay giá trị hay biểu thức cần ép).

Ví dụ trong trường hợp trên a, b ta khai báo: int a,b;

Thì khi in ra ta có thể dùng 1 trong 3 cách sau đây đều cho ra kết quả đúng.

cout << (long long)(a) + b;

cout << a + (long long)(b);

cout<<a+(long long)b;

Lúc này kết quả khi ta nhập a =2000000000; b=2000000000 thì sẽ cho kết quả là 4000000000

Nhưng nếu viết cout << (long long)(a+b); thì kết quả sẽ ra không đúng. Trong trường hợp này chương trình sẽ lấy kết quả a+b trước rồi mới ép kiểu nên vẫn xẩy ra hiện tượng tràn số khi thực hiện phép toán. Ở đây ta chú ý khi hai toán hạng (số hạng) tác động vào nhau bởi toán tử (các phép toán) thì kết quả sẽ trả về kiểu dữ liệu cao nhất của 2 toán hạng. Ví dụ trên là a b đều là kiểu int, nếu ta viết a + (long long)b nghĩa là giá trị có kiểu int cộng với ép giá trị của b về kiểu long long nên kết quả của phép cộng là kiểu giá trị cao hơn (vì kiểu long long > int)

 

Để hiểu thêm ta đoạn chương trình sau:

int a, b, c;

long long d;

d = a+ b + c; // khi a, b, c nằm ở cận trên của kiểu int sẽ xảy ra hiện tượng tràn số

d = (long long)a + b + c; //không bị tràn số (kết quả ra đúng)

d = a + (long long)b + c;  //không bị tràn số (kết quả ra đúng)

d = a + b + (long long)c; /*bị tràn số phần a+b vì nó tính giá trị từ trái qua phải */

 

CÁC PHẢN HỒI

Back to Top