在对该变量进行操作时,在 C++ 中以更少的编译时间将非常大的整数值存储在变量中的各种方法有哪些
What are various methods to store very large integer value in a variable with less compilation time in C++ when doing operation on that variable
我应该如何处理这个变量以使其存储大量数字而不下载任何新的libraries.I我正在谈论使用一些操作,如散列或数组或我不知道的东西。
如果您不需要对该变量执行任何操作并且不能使用任何库,包括 C++ 标准库,则使用
const char* x = "1119191991900234245239919234772376189636415308431";
否则下一个最好的选择是
std::string x = "1119191991900234245239919234772376189636415308431";
这样的编码连初等运算都可以,字符串中n
位置的数字值为x[n] - '0'
.
但这一切真的很愚蠢。建议您查看作为 Boost 发行版一部分的大数库。参见 www.boost.org。
为了好玩,我写了一些只适用于字符串的东西。顺便说一下,你给出的数字非常大,大约是我们太阳系质量千克的五分之一。
有两种方法。第一个将数字加一并检查它是否是回文。这是一个较慢的版本,但仍然可以在合理的时间内处理最多约 16 位数的数字。
第二种方法是更好的方法,它基本上是将数字的左侧复制到右侧,几乎是即时的。由于现在的代码,您可以 运行 通过两者来 cross-reference 结果。
我不能说它是 fool-proof,我敢肯定其中有错误,但它似乎有效,而且我写它确实很有趣。此外,如果您不允许使用任何库,那么重构起来相当容易,只需使用原始字符串并在函数中传递大小。
#include <iostream>
#include <string>
#include <chrono>
#include <stdexcept>
#include <cstring>
using namespace std::chrono;
using namespace std;
auto startT = high_resolution_clock::now();
auto endT = high_resolution_clock::now();
double timeTaken;
#define STARTCLOCK startT = high_resolution_clock::now();
#define STOPCLOCK endT = high_resolution_clock::now();
#define PRINT_ELAPSED_TIME timeTaken = duration_cast<milliseconds>(endT - startT).count() / 1000.0; \
cout << "Process took " << timeTaken << " seconds\n\n";
void addOneTo(std::string& value)
{
int64_t idx = value.size();
do
{
--idx;
if (idx < 0) {
memset(&value[0], '0', value.size());
value.insert(value.begin(), '1');
return;
}
value[idx] += char(1);
if (value[idx] > '9') { value[idx] = '0'; }
} while (value[idx] == '0');
}
bool isPalindrome(const std::string& number)
{
const char* start = &number[0];
const char* end = &number[number.size() - 1];
while (start <= end)
{
if (*start != *end) return false;
++start;
--end;
}
return true;
}
std::string getSmallestPalindromeByBruteForceBiggerThan(std::string num)
{
if (num.empty()) throw std::runtime_error("Empty string");
while (true)
{
addOneTo(num);
if (isPalindrome(num)) return num;
}
}
std::string getSmallestPalindromeOptimisedWayBiggerThan(std::string num)
{
if (num.empty()) throw std::runtime_error("Empty string");
addOneTo(num);
if (num.size() == 1) return num;
int64_t left;
int64_t right;
left = num.size() / 2 - 1;
if (num.size() % 2 == 0) right = num.size() / 2;
else right = num.size() / 2 + 1;
if (num[left] < num[right])
{
++num[left];
num[right] = num[left];
}
for (; left >= 0 && right < num.size(); --left, ++right)
{
num[right] = num[left];
}
return num;
}
int main()
{
string number = "60819750046451377";
STARTCLOCK
string palindrome = getSmallestPalindromeByBruteForceBiggerThan(number);
cout << "____BRUTE FORCE____\n";
cout << "Smallest palindrome = \n" << palindrome << '\n';
STOPCLOCK
PRINT_ELAPSED_TIME
STARTCLOCK
palindrome = getSmallestPalindromeOptimisedWayBiggerThan(number);
cout << "____OPTIMISED____\n";
cout << "Smallest palindrome = \n" << palindrome << '\n';
STOPCLOCK
PRINT_ELAPSED_TIME
cin.ignore();
}
我应该如何处理这个变量以使其存储大量数字而不下载任何新的libraries.I我正在谈论使用一些操作,如散列或数组或我不知道的东西。
如果您不需要对该变量执行任何操作并且不能使用任何库,包括 C++ 标准库,则使用
const char* x = "1119191991900234245239919234772376189636415308431";
否则下一个最好的选择是
std::string x = "1119191991900234245239919234772376189636415308431";
这样的编码连初等运算都可以,字符串中n
位置的数字值为x[n] - '0'
.
但这一切真的很愚蠢。建议您查看作为 Boost 发行版一部分的大数库。参见 www.boost.org。
为了好玩,我写了一些只适用于字符串的东西。顺便说一下,你给出的数字非常大,大约是我们太阳系质量千克的五分之一。
有两种方法。第一个将数字加一并检查它是否是回文。这是一个较慢的版本,但仍然可以在合理的时间内处理最多约 16 位数的数字。
第二种方法是更好的方法,它基本上是将数字的左侧复制到右侧,几乎是即时的。由于现在的代码,您可以 运行 通过两者来 cross-reference 结果。
我不能说它是 fool-proof,我敢肯定其中有错误,但它似乎有效,而且我写它确实很有趣。此外,如果您不允许使用任何库,那么重构起来相当容易,只需使用原始字符串并在函数中传递大小。
#include <iostream>
#include <string>
#include <chrono>
#include <stdexcept>
#include <cstring>
using namespace std::chrono;
using namespace std;
auto startT = high_resolution_clock::now();
auto endT = high_resolution_clock::now();
double timeTaken;
#define STARTCLOCK startT = high_resolution_clock::now();
#define STOPCLOCK endT = high_resolution_clock::now();
#define PRINT_ELAPSED_TIME timeTaken = duration_cast<milliseconds>(endT - startT).count() / 1000.0; \
cout << "Process took " << timeTaken << " seconds\n\n";
void addOneTo(std::string& value)
{
int64_t idx = value.size();
do
{
--idx;
if (idx < 0) {
memset(&value[0], '0', value.size());
value.insert(value.begin(), '1');
return;
}
value[idx] += char(1);
if (value[idx] > '9') { value[idx] = '0'; }
} while (value[idx] == '0');
}
bool isPalindrome(const std::string& number)
{
const char* start = &number[0];
const char* end = &number[number.size() - 1];
while (start <= end)
{
if (*start != *end) return false;
++start;
--end;
}
return true;
}
std::string getSmallestPalindromeByBruteForceBiggerThan(std::string num)
{
if (num.empty()) throw std::runtime_error("Empty string");
while (true)
{
addOneTo(num);
if (isPalindrome(num)) return num;
}
}
std::string getSmallestPalindromeOptimisedWayBiggerThan(std::string num)
{
if (num.empty()) throw std::runtime_error("Empty string");
addOneTo(num);
if (num.size() == 1) return num;
int64_t left;
int64_t right;
left = num.size() / 2 - 1;
if (num.size() % 2 == 0) right = num.size() / 2;
else right = num.size() / 2 + 1;
if (num[left] < num[right])
{
++num[left];
num[right] = num[left];
}
for (; left >= 0 && right < num.size(); --left, ++right)
{
num[right] = num[left];
}
return num;
}
int main()
{
string number = "60819750046451377";
STARTCLOCK
string palindrome = getSmallestPalindromeByBruteForceBiggerThan(number);
cout << "____BRUTE FORCE____\n";
cout << "Smallest palindrome = \n" << palindrome << '\n';
STOPCLOCK
PRINT_ELAPSED_TIME
STARTCLOCK
palindrome = getSmallestPalindromeOptimisedWayBiggerThan(number);
cout << "____OPTIMISED____\n";
cout << "Smallest palindrome = \n" << palindrome << '\n';
STOPCLOCK
PRINT_ELAPSED_TIME
cin.ignore();
}