[英]Create big numbers by BCD - C++
我想創建代碼來幫助我獲得比MAXINT大的數字。 我聽說我可以使用二進制代碼十進制執行此操作,然后將較大數字的每兩個十進制數字(轉換為BCD)保留在char中。 但是該怎么做呢? 我應該將字符串作為輸入,然后以某種方式將每個十進制數字轉換為BCD? 以及如何將兩個轉換后的十進制數字轉換為一個字符? 我是C ++的新手,不知道該怎么辦。
PS我不想使用針對此類問題的“特殊”庫。
事實證明,這實際上很簡單。 我們如何將其提升到一個新的水平呢?
下面是一個BCD編號的實現,該編號具有無限(或盡可能多的存儲空間)大小。 它僅支持正整數。 我將擴展它以支持負數(或實數)作為練習。
首先,是第一件事:是的,我們想將我們的數字作為字符串獲取,然后從中進行構建。 由於它只是一個整數,因此實際上很容易做到。 我們主要創建一個輔助函數來幫助我們識別所有數字。
int char_to_int(const char c) {
int ret = c - '0';
if(ret > 9 || ret < 0) throw 1; // for simplicity. Use a class derived from std::exception instead.
return ret;
}
現在,我們可以嘗試為大量用戶實現輸入和輸出。
有那個幫手,將字符串轉換為BCD編碼的緩沖區很容易。 常見的實現可能如下所示:
int main() {
unsigned char bignum[10]; // stores at most 20 BCD digits.
std::memset(bignum, 0, sizeof(bignum));
std::string input;
std::cin >> input;
try {
if (input.size() > 20) throw 1; // Avoid problems with buffer overflow.
for (int i=1;i<=input.size();i++) {
int n = char_to_int(input[input.size()-i]);
bignum[sizeof(bignum) - (i+1)/2] |= n << (i%2)*4; // These are bitwise operations. Google them!
}
}
catch(int) {
std::cout << "ERROR: Invalid input.\n";
return 0; // Exit cleanly.
}
// bignum is now filled. Let's print it to prove.
for (int i=0;i<sizeof(bignum);i++) {
int first_digit = bignum[i] & '\x0F'; // Right side, doesn't need to shift.
int second_digit = (bignum[i] & '\xF0')>>4; // Left side, shifted.
std::cout << first_digit << second_digit;
}
}
但是,這不是非常節省空間的。 請注意,即使我們的數字很小,我們也必須存儲所有20位數字! 如果我們需要1000位數字怎么辦? 如果我們需要1000個可能具有或不具有這1000個數字的數字怎么辦? 這也容易出錯:看起來我們必須記住要初始化數組,並在轉換前進行邊界檢查以避免緩沖區溢出。
我們可以使用std :: vector改善實現:
int main() {
std::vector<unsigned char> bignum; // stores any quantity of digits.
std::string input;
std::cin >> input;
try {
// For an odd number of digits we want a trailling zero at the end.
if(input.size()%2) n.num_vec.push_back(char_to_int(input[0]));
for (unsigned i=input.size()%2;i<input.size();i+=2) {
int left = char_to_int(input[i]);
int right = char_to_int(input[i+1]);
n.num_vec.push_back(0);
n.num_vec.back() = left << 4;
n.num_vec.back() |= right;
}
}
catch(int) {
std::cout << "ERROR: Invalid input.\n";
exit(0); // Exit cleanly.
}
// bignum is now filled. Let's print it to prove.
for (unsigned i=0;i<bignum.size();++i) {
// Notice that we inverted this from the previous one! Try to think why.
int first_digit = (bignum[i] & '\xF0')>>4; // Left side, shifted.
int second_digit = bignum[i] & '\x0F'; // Right side, doesn't need to shift.
if(i || first_digit) std::cout << first_digit; // avoid printing trailling 0.
std::cout << second_digit;
}
}
看起來不錯,但是那太麻煩了。 理想情況下,bignumber用戶不必處理向量位置以及所有龐然大物。 我們想要編寫行為類似的代碼:
int main() {
int a;
cin >> a;
cout << a;
}
它應該可以正常工作。
原來這是可能的! 只需將bignum包裝到一個類中,並添加一些有用的運算符:
class bignum {
std::vector<unsigned char> num_vec;
template<typename T>
friend T& operator<<(T& is, bignum& n);
template<typename T>
friend T& operator>>(T& os, bignum& n);
};
// Get input from any object that behaves like an std::istream (i.e.: std::cin)
template<typename T>
T& operator>>(T& is, bignum& n) {
std::string input;
is >> input;
n.num_vec.reserve(input.size());
if(input.size()%2) n.num_vec.push_back(char_to_int(input[0]));
for (unsigned i=input.size()%2;i<input.size();i+=2) {
int left = char_to_int(input[i]);
int right = (i+1) != input.size()?char_to_int(input[i+1]):0; // If odd number of digits, avoid getting garbage.
n.num_vec.push_back(0);
n.num_vec.back() = left << 4;
n.num_vec.back() |= right;
}
return is;
}
// Output to any object that behaves like an std::ostream (i.e.: std::cout)
template<typename T>
T& operator<<(T& os, bignum& n) {
for (unsigned i=0;i<n.num_vec.size();++i) {
int first_digit = (n.num_vec[i] & '\xF0')>>4; // Left side, shifted.
int second_digit = n.num_vec[i] & '\x0F'; // Right side, doesn't need to shift.
if(i || first_digit) os << first_digit; // avoid printing trailling 0.
os << second_digit;
}
return os;
}
然后我們的主要功能看起來更具可讀性:
int main() {
bignum a;
try {
std::cin >> a;
}
catch(int) {
std::cout << "ERROR: Invalid input.\n";
return 0; // Exit cleanly.
}
std::cout << a;
}
在這里,我們有它。 當然,如果沒有加,乘等運算符,它不是很有用。 我把它們留作練習。 代碼,代碼和更多代碼,很快對您來說就像小菜一碟。
請隨時提出任何問題。 好的編碼!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.