我的程序运行在所有数字上,但在计算BigInt MAX(INT_MAX)时不运行。当我试着运行这个时,它给了我一个分段错误。下面是BigInt类:
#include <iostream>
#include <limits.h>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
class BigInt
{
private:
vector<char> v;
public:
BigInt()
{
v.push_back('0');
}
BigInt(int num)
{
while (num != 0)
{
v.push_back(num % 10);
num /= 10;
}
}
BigInt(string str) //3
{
for (int i = str.length() - 1; i >= 0; i--)
v.push_back(str[i] - '0');
}
BigInt operator+(BigInt b)
{
BigInt result;
int carry = 0;
for (int i = 0; i < max(v.size(), b.v.size()); i++)
{
int sum = carry;
if (i < v.size())
sum += v[i];
if (i < b.v.size())
sum += b.v[i];
result.v.push_back(sum % 10);
carry = sum / 10;
}
if (carry != 0)
result.v.push_back(carry);
return result;
}
BigInt operator++( )
{
*this = *this + BigInt(1);
return *this;
}
BigInt operator++(int)
{
BigInt temp = *this;
*this = *this + BigInt(1);
return temp;
}
BigInt operator*(BigInt b)
{
BigInt result;
result.v.resize(v.size() + b.v.size());
for (int i = 0; i < v.size(); i++)
for (int j = 0; j < b.v.size(); j++)
result.v[i + j] += v[i] * b.v[j];
for (int i = 0; i < result.v.size() - 1; i++)
{
result.v[i + 1] += result.v[i] / 10;
result.v[i] %= 10;
}
while (result.v.back() == 0 && result.v.size() > 1)
result.v.pop_back();
return result;
}
BigInt operator+=(BigInt b)
{
*this = *this + b;
return *this;
}
BigInt half()
{
BigInt result;
int remainder = 0;
for (int i = v.size() - 1; i >= 0; i--)
{
int current = remainder * 10 + v[i];
int digit = current / 2;
if (digit != 0 || !result.v.empty())
result.v.push_back(digit);
remainder = current % 2;
}
if (result.v.empty())
result.v.push_back(0);
return result;
}
bool isOdd()
{
return v[0] % 2 == 1;
}
bool isEven()
{
return !isOdd();
}
bool operator==(BigInt b)
{
if (v.size() != b.v.size())
return false;
for (int i = 0; i < v.size(); i++)
if (v[i] != b.v[i])
return false;
return true;
}
bool operator<(BigInt b)
{
if (v.size() != b.v.size())
return v.size() < b.v.size();
for (int i = v.size() - 1; i >= 0; i--)
if (v[i] != b.v[i])
return v[i] < b.v[i];
return false;
}
friend ostream& operator<<(ostream& os, const BigInt& b){
if (b.v.size() < 9)
{
for (auto it = b.v.rbegin(); it != b.v.rend(); ++it)
{
os << static_cast<int>(*it);
}
}
else
{
os << static_cast<int>(b.v.back()) << ".";
for (size_t i = 1; i <= 7; ++i)
{
os << static_cast<int>(b.v[b.v.size() - i - 1]);
}
os << "e" << b.v.size() - 1;
}
return os;
}
};
下面是驱动程序代码:
struct ThreeNp1
{
BigInt start;
BigInt steps;
BigInt max;
BigInt odd;
BigInt even;
};
void print(ThreeNp1 temp)
{
cout << "start:" << temp.start << endl;
cout << "steps:" << temp.steps << endl;
cout << "max:" << temp.max << endl;
cout << "odds:" << temp.odd << endl;
cout << "evens:" << temp.even << endl;
}
void findThreeNp1(BigInt n, ThreeNp1 &Np1, bool printSteps = false)
{
if (printSteps)
{
cout << "->" << '(' << n << ')';
}
if (Np1.max < n)
Np1.max = n;
if (n == BigInt(1))
{
return;
}
else if (n.isEven())
{
Np1.even++;
Np1.steps++;
findThreeNp1(n.half(), Np1, printSteps);
}
else if (n.isOdd())
{
Np1.odd++;
Np1.steps++;
BigInt tempN(n);
findThreeNp1(tempN * BigInt(3) + BigInt(1), Np1, printSteps);
}
else
{
cout << "How the hell did I get here?\n";
return;
}
}
int main()
{
BigInt MAX(INT_MAX);
cout << "The largest integer is " << MAX << endl;
cout << "Twice the largest integer is " << MAX + MAX << endl;
BigInt start(INT_MAX);
bool printSteps = false;
ThreeNp1 N = {start, 0, 0, 0, 0};
findThreeNp1(start, N, printSteps);
cout << endl;
print(N);
return 0;
}
我已经重写了很多次代码,我已经检查了我的逻辑错误。我能想到的办法都试过了。如果有人看到任何错误或我可以改善,让这件事运行,请让我知道。
2条答案
按热度按时间a14dhokn1#
segfault是由于递归函数
findThreeNp1()
耗尽了它的堆栈空间,我/@john将根本原因归因于以下缺陷:1.默认构造函数应该将
vector<...> a
留空。否则BigInt(1)+ BigInt(1)将变为20。这需要一个特殊的情况,当vector.size() == 0
在operator<<
和isOdd()
。vector<char> v
意味着它是实现定义的,如果它是有符号的或无符号的。在我的系统上,它是签名的,这意味着99 * 99会触发溢出。将类型更改为unsigned char
。half()
不工作。BigInt(20).half()
不应该是01
。我重写了它并进行了最低限度的测试。下面是生成的程序:
输出为:
下面是
findThreeNp1()
的迭代版本。一旦其他问题得到解决,它就不会有太大的区别(在10 k外部运行时,它的速度提高了约2.5%):Np1.steps == Np1.odd + Np1.even
所以我们只需要其中两个变量。sqxo8psd2#
你的错误在这里
那应该是
因为你的类存储整数而不是数字。所以零是
0
而不是"0"
。具体来说,你的乘法代码从
result
开始,用BigInt result;
初始化为零,但因为你的默认构造函数没有正确初始化为零,乘法例程也有bug,这导致了无限递归和堆栈溢出,当你试图计算Collatz猜想系列时。调试器很快就发现了这个错误,你应该学习如何使用它。
更新(已更正)
您的
half
例程有问题。您处理要从最高有效位到最低有效位减半的数字的位数。但是您将结果数字按相同的顺序(最重要的数字在前)推送到result
变量。这与您的类的工作方式相矛盾,该类首先存储最低有效位。结果是,在half
操作之后,数字是正确的,但以相反的顺序存储。由于默认构造函数的工作方式,还包含了一个额外的零数字。可能默认构造函数应该让vector为空。将零
BigInt
打印为"0"
是一种特殊情况,应该在打印例程中处理,而不是在计算例程中处理。这将简化代码。例如,BigInt x;
和BigInt y(0);
产生不同的内部向量。这也是一个bug。