Trong thế giới lập trình, kiểu số nguyên là một trong những kiểu dữ liệu cơ bản nhất. Tuy nhiên, các kiểu số nguyên truyền thống trong C++, như `int`, `long`, hay `long long`, đều có giới hạn về phạm vi giá trị mà chúng có thể biểu diễn. Điều này gây ra nhiều vấn đề khi làm việc với các con số cực lớn, vượt quá khả năng lưu trữ của chúng. Để giải quyết vấn đề này, chúng ta cần đến **số nguyên vô hạn độ chính xác** (infinite precision integer), một giải pháp cho phép biểu diễn và tính toán với các số lớn tùy ý. Bài viết này sẽ đi sâu vào việc triển khai số nguyên vô hạn độ chính xác trong C++20, bao gồm hỗ trợ số âm và các phép toán số học cơ bản.
**Số nguyên vô hạn độ chính xác**, còn được gọi là số nguyên tùy ý (arbitrary-precision integer) hoặc số nguyên lớn (big integer), là một kiểu dữ liệu có khả năng biểu diễn các số với kích thước bất kỳ, không giới hạn số lượng chữ số. Không giống như các kiểu số nguyên truyền thống với phạm vi cố định, số nguyên vô hạn độ chính xác có thể tự động mở rộng hoặc thu hẹp để phù hợp với kích thước của số. Điều này rất quan trọng trong các ứng dụng đòi hỏi độ chính xác cao khi xử lý các con số khổng lồ, ví dụ như tính toán khoa học, mật mã học, hay tài chính.
Dưới đây là một ví dụ về cách triển khai số nguyên vô hạn độ chính xác trong C++20, hỗ trợ số âm và các phép toán cơ bản. Chúng ta sẽ sử dụng `std::string` để lưu trữ các chữ số của số nguyên, cho phép nó mở rộng theo nhu cầu.
#include <iostream>
#include <string>
#include <algorithm>
class InfinitePrecisionInteger {
private:
std::string digits;
bool isNegative;
public:
// Constructor
InfinitePrecisionInteger(const std::string& num) : digits(num), isNegative(false) {
if (digits[0] == '-') {
isNegative = true;
digits = digits.substr(1); // Remove the negative sign
}
}
// Addition
InfinitePrecisionInteger add(const InfinitePrecisionInteger& other) const {
std::string result = "";
int carry = 0;
int i = digits.length() - 1;
int j = other.digits.length() - 1;
while (i >= 0 || j >= 0 || carry) {
int digit1 = (i >= 0) ? digits[i] - '0' : 0;
int digit2 = (j >= 0) ? other.digits[j] - '0' : 0;
int sum = digit1 + digit2 + carry;
carry = sum / 10;
result = std::to_string(sum % 10) + result;
i--;
j--;
}
return InfinitePrecisionInteger(result);
}
// Subtraction (basic, assumes first number is larger)
InfinitePrecisionInteger subtract(const InfinitePrecisionInteger& other) const {
std::string result = "";
int borrow = 0;
int i = digits.length() - 1;
int j = other.digits.length() - 1;
while (i >= 0 || j >= 0) {
int digit1 = (i >= 0) ? digits[i] - '0' : 0;
int digit2 = (j >= 0) ? other.digits[j] - '0' : 0;
int diff = digit1 - digit2 - borrow;
if (diff < 0) {
diff += 10;
borrow = 1;
} else {
borrow = 0;
}
result = std::to_string(diff) + result;
i--;
j--;
}
// Remove leading zeros
size_t firstNonZero = result.find_first_not_of('0');
if (firstNonZero == std::string::npos) {
return InfinitePrecisionInteger("0"); // Result is zero
}
result = result.substr(firstNonZero);
return InfinitePrecisionInteger(result);
}
// Simple multiplication (can be optimized)
InfinitePrecisionInteger multiply(const InfinitePrecisionInteger& other) const {
InfinitePrecisionInteger result("0");
InfinitePrecisionInteger temp;
for(int i = other.digits.length() - 1; i >= 0; i--){
int digit = other.digits[i] - '0';
temp = *this;
for(int j = 1; j < digit; j++) {
temp = temp.add(*this);
}
for (int k = 0; k < other.digits.length() - 1 - i; k++)
temp.digits += '0';
result = result.add(temp);
}
return result;
}
// Output
void print() const {
if (isNegative) {
std::cout << "-";
}
std::cout << digits << std::endl;
}
};
int main() {
InfinitePrecisionInteger num1("12345678901234567890");
InfinitePrecisionInteger num2("98765432109876543210");
std::cout << "Number 1: ";
num1.print();
std::cout << "Number 2: ";
num2.print();
InfinitePrecisionInteger sum = num1.add(num2);
std::cout << "Sum: ";
sum.print();
InfinitePrecisionInteger difference = num1.subtract(num2);
std::cout << "Difference: ";
difference.print();
InfinitePrecisionInteger product = num1.multiply(num2);
std::cout << "Product: ";
product.print();
return 0;
}
**Giải thích code:**
Đoạn code `main()` trong ví dụ trên minh họa cách tạo đối tượng `InfinitePrecisionInteger`, thực hiện các phép toán cộng, trừ, nhân và in kết quả. Bạn có thể thay đổi các giá trị đầu vào để thử nghiệm với các số lớn hơn.
**Số nguyên vô hạn độ chính xác** được sử dụng rộng rãi trong các lĩnh vực sau:
Việc triển khai **số nguyên vô hạn độ chính xác** trong C++20 cung cấp một giải pháp mạnh mẽ để xử lý các phép toán với số lớn. Mặc dù có một số hạn chế về hiệu suất, nhưng nó vẫn là một công cụ vô giá trong nhiều ứng dụng khác nhau, nơi độ chính xác là yếu tố then chốt. Việc hiểu rõ về cách thức hoạt động và các ứng dụng của nó sẽ giúp bạn giải quyết các vấn đề phức tạp liên quan đến tính toán số học trong các dự án của mình.
Bài viết liên quan