Các bài toán số lớn lập trình c++ năm 2024

Trong các ngôn ngữ lập trình, khả năng lưu trữ của kiểu số thường có 1 giới hạn. Ví dụ kiểu dữ liệu

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

0 của ngôn ngữ C++ thường giới hạn ở mức

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

1 đến

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

2.

Có những bài toán thực tế cần thao tác với những số vượt quá giới hạn này. Do đó cần phải có những phương pháp để giải quyết như:

  • Sử dụng những thư viện hỗ trợ thêm.
  • Tự xây dựng các kiểu dữ liệu này và cung cấp các phương thức lưu trữ và thao tác.

Phép cộng hai số lớn

Lựa chọn kiểu dữ liệu

Với một số nguyên lớn có 20 độ dài 20 ký số, một biến thông thường không thể hiện được toàn bộ số lớn này. Vì vậy chọn cách dùng nhiều biến để biểu diễn từng chữ số, như vậy có thể sử dụng một mảng các ký số để biểu diễn cho một số lớn.

Một chữ số có giá trị từ 0 – 9 nên để tối ưu và đơn giản cho thao tác nhập mảng, có thể sử dụng mảng kiểu

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

3.

Hàm cộng hai số lớn có dạng:

char* addBigNumber[char* number1, char* number2];

Với hai chuỗi

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

4,

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

5 là hai số lớn cần tính toán.

Hiện thực phép toán

Có 2 trường hợp sau khi cộng hai số

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

4 và

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

5:

  • size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false; 4 có chiều dài [số ký số] lớn hơn hoặc bằng số size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false; 5.
  • size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false; 5 có chiều dài lớn hơn hoặc bằng số size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false; 4.

Để tổng quát hóa hai trường hợp trên, cần so sánh chiều dài hai số

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

4 và

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

5, nếu số

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

5 có chiều dài lớn hơn số

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

4, thực hiện đảo giá trị hai pointer chứa địa chỉ mảng

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

4 và mảng

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

5. Từ đó,

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

4 luôn có chiều dài lớn hơn hoặc bằng

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

5.

Để đơn giản cho thao tác với chuỗi, sử dụng hàm

int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0';

0 trong thư viện

int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0';

1.

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

Hàm

int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0';

2 được định nghĩa như sau:

void swapPointer[char* a, char* b] { char* temp = *a; *a = *b; *b = temp; }

Khai báo một số biến cần thiết trong quá trình tính toán như sau:

  • int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0'; 3, int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0'; 4 là chiều dài hai số size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false; 4, size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false; 5.
  • int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0'; 7 là kết quả int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0'; 8, chiều dài của int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0'; 7 luôn bằng hoặc lớn hơn chiều dài số size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false; 4 một đơn vị tùy trường hợp nên khi cấp phát cho int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0'; 7 cần thêm 1 byte và 1 byte nữa là dành cho ký tự rỗng cuối chuỗi là 2 byte.
  • if [remember] temp++; remember = temp > 9; temp = temp % 10; 2 là biến chỉ trạng thái “nhớ” của phép tính khi cộng 2 chữ số, ban đầu là if [remember] temp++; remember = temp > 9; temp = temp % 10; 3.

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

Có hai công đoạn khi thực hiện cộng 2 số:

  • Tính tổng các chữ số của cả size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false; 4 và size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false; 5 [phần bên phải].
  • Tính tổng các chữ số của size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false; 4 với if [remember] temp++; remember = temp > 9; temp = temp % 10; 7 [phần bên trái].

Như vậy cần hai vòng lặp để làm những việc này.

Bước 1

Số lần lặp của công đoạn này sẽ là

if [remember] temp++; remember = temp > 9; temp = temp % 10;

8

for [int i = 0; i < number2Len; i++] { //... }

Cần tính tổng các chữ số từ phải qua trái, lấy giá trị các chữ số này bằng cách sử dụng

if [remember] temp++; remember = temp > 9; temp = temp % 10;

9 và

*[result + number1Len - i] = temp + '0';

0.

Mỗi giá trị hiện tại đang được lưu trong mảng với kiểu

*[result + number1Len - i] = temp + '0';

1, để lấy được chính xác giá trị kiểu số của các chữ số này, trừ mỗi giá trị cho

*[result + number1Len - i] = temp + '0';

2 [

*[result + number1Len - i] = temp + '0';

3]. Ví dụ: ký tự

*[result + number1Len - i] = temp + '0';

4 trong kiểu char có giá trị là

*[result + number1Len - i] = temp + '0';

5, lấy

*[result + number1Len - i] = temp + '0';

6 được 9.

Dùng một biến tạm để lưu tổng của 2 giá trị này:

int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0';

Ví dụ: khi cộng

*[result + number1Len - i] = temp + '0';

7 và

*[result + number1Len - i] = temp + '0';

8, kết quả là

*[result + number1Len - i] = temp + '0';

9

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

0 nên chỉ lấy chữ số hàng đơn vị là

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

1, nhớ

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

1, tiếp theo, lấy

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

3 được

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

4, vì có nhớ nên ghi

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

5. Kết quả là

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

6.

Theo logic đó, tiếp xét giá trị biến

if [remember] temp++; remember = temp > 9; temp = temp % 10;

2, nếu là

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

8 thì cộng

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

9 lên 1 đơn vị, nếu

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

9 có giá trị

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

0, gán

int temp = number1[number1Len - number2Len - i – 1] - '0';

2, ngược lại ta gán

int temp = number1[number1Len - number2Len - i – 1] - '0';

3. Để lấy chữ số hàng đơn vị của

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

9, ta lấy

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

9 chia phần dư cho 10.

if [remember] temp++; remember = temp > 9; temp = temp % 10;

Tổng các chữ số của

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

4 và

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

5 đã được tính với cách trên, gán giá trị này vào mảng

int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0';

7. Tương tự cách làm ở trên, để ghi được ký tự

*[result + number1Len - i] = temp + '0';

4 vào mảng, cộng số

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

00 với

*[result + number1Len - i] = temp + '0';

2 [

*[result + number1Len - i] = temp + '0';

3].

*[result + number1Len - i] = temp + '0';

Vậy ta có code hoàn chỉnh cho vòng lặp vừa rồi như sau:

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

Với vòng lặp này, có thể cộng hai số lớn có chiều dài bằng nhau.

Bước 2

Tương tự các bước của công đoạn thứ nhất, số lần lặp của công đoạn này là:

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

03.

Giai đoạn này lấy giá trị các ký số của

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

4 bằng cách sử dụng:

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

05, từ đó có giá trị biến

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

9 là:

int temp = number1[number1Len - number2Len - i – 1] - '0';

Tương tự giá trị

int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0';

7 như sau:

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

0

Code hoàn chỉnh:

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

1

Để đánh dấu kết thúc chuỗi

int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0';

7, gán:

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

2

Ví dụ

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

09, làm lần lượt các bước như trên, được result có 4 chữ số, nhưng đáp án là

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

10 có 5 ký số. Để làm được việc này, xét giá trị biến

if [remember] temp++; remember = temp > 9; temp = temp % 10;

2, nếu là

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

8: gán giá trị

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

13, ngược lại, dịch tất cả các phần tử của mảng

int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0';

7 sang bên trái một đơn vị.

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

3

Cuối cùng, trả về

int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0';

7 là kết quả của

int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0';

8.

Kiểm thử với hàm

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

17:

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

4

Kết quả:

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

18.

Code hoàn chỉnh cộng 2 số lớn

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

5

Phép trừ hai số lớn

Hàm trừ hai số lớn có dạng:

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

6

Với hai chuỗi

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

4,

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

5 là hai số lớn cần tính toán.

Hiện thực phép toán

Khi trừ hai số

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

4 và

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

5, phải biết số nào lớn hơn để thực hiện phép trừ. Ví dụ khi thực hiện phép toán

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

23. Xác định 100 lớn hơn 9 nên lấy

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

24, thêm dấu trừ và được kết quả

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

25.

Để cho thuận tiện kiểm tra

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

5 có lớn

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

4 hay không? Nếu có thì ta đảo hai pointer chứa địa chỉ hai mảng

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

4,

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

5 và thêm dấu trừ vào trước kết quả.

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

7

Đoạn code trên kiểm tra độ dài 2 số, nếu bằng nhau sẽ tiếp tục so sánh từng chữ số từ phải qua trái để tìm ra số lớn hơn, sau đó đảo vị trí các pointer [nếu cần].

Khai báo và gán giá trị một số biến cần thiết trong quá trình tính toán như sau:

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

8

int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0';

7 được cấp phát thêm 2 bytes: một byte dành cho ký tự rỗng cuối chuỗi, một byte cho dấu trừ đầu chuỗi nếu kết quả là số âm.

Có hai công đoạn khi thực hiện trừ hai số:

  • Tính hiệu các chữ số của size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false; 4 cho size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false; 5 [phần bên phải].
  • Tính hiệu các chữ số của size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false; 4 với if [remember] temp++; remember = temp > 9; temp = temp % 10; 7 [phần bên trái].

Như vậy cần hai vòng lặp để làm việc này.

Bước 1

Số lần lặp của công đoạn này là

int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0';

4:

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

9

Cần tính hiệu các ký số từ phải qua trái, vì phép trừ nên chỉ cần số chênh lệch giữa 2 số:

void swapPointer[char* a, char* b] { char* temp = *a; *a = *b; *b = temp; }

0

Theo như logic của phép trừ, khi một chữ số của

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

4 nhỏ hơn

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

5, khi trừ phải mượn 1 từ chữ số tiếp theo bên trái. Và kết quả phép trừ được cộng thêm 10, kết quả phép trừ tiếp theo sẽ giảm 1 đơn vị do mượn 1 từ phép trừ vừa rồi:

void swapPointer[char* a, char* b] { char* temp = *a; *a = *b; *b = temp; }

1

Gán kết quả vừa tính vào

int temp = number2[number2Len - i - 1] - '0' + number1[number1Len - i - 1] - '0';

7:

void swapPointer[char* a, char* b] { char* temp = *a; *a = *b; *b = temp; }

2

Code hoàn chỉnh cho vòng lặp vừa rồi như sau:

void swapPointer[char* a, char* b] { char* temp = *a; *a = *b; *b = temp; }

3

Bước 2

Số lần lặp của công đoạn này là:

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

03.

Giai đoạn này chỉ cần lấy giá trị các ký số của

size_t number1Len = strlen[number1], number2Len = strlen[number2]; char* result = new char[number1len + 2]; bool remember = false;

4 bằng cách sử dụng:

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

41, từ đó có giá trị biến

for [int i = 0; i < number2Len; i++] { int temp = [b + number2Len - i - 1] - '0' + [a + number1Len - i - 1] - '0'; if [remember]

temp++;
remember = temp > 9; temp = temp % 10; result[number1Len - i] = temp + '0'; }

9 là:

void swapPointer[char* a, char* b] { char* temp = *a; *a = *b; *b = temp; }

4

tương tự ta có giá trị result như sau:

void swapPointer[char* a, char* b] { char* temp = *a; *a = *b; *b = temp; }

5

vậy ta có code hoàn chỉnh:

void swapPointer[char* a, char* b] { char* temp = *a; *a = *b; *b = temp; }

6

Ví dụ:

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

43 với những gì đã làm ta được kết quả là

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

44, xóa số 0 trước chuỗi và thêm dấu trừ [nếu có] vào đầu chuỗi dựa vào giá trị biến

if [strlen[number1] < strlen[number2]] { swapPointer[&number1, &number2]; }

45.

Chủ Đề