自定义大数类划分的问题 (C++)
我正在为大数字类(单个数字的无限长度)编写自定义算术,
当 A 远大于 B 时,使用多个递减数字 A 除以 B 会失败。 我正在尝试实施书面除法,但我发现它对我的情况来说太复杂了。
我无法将数字存储在字符串中(这是该项目的主要限制),因此我将它们以 4 位数字为一组存储在 int 列表中。 我试图将其视为整个 4 位数字结构是流行的书面除法中的单个数字,但我在实现过程中通过重载 / 运算符迷失了方向。
我想得到一个提示,如果我正在做除法的最后一个主要部分,是否正确?如果在这个类中划分,我该如何改进方法?
struct Node{
int value;
Node* next,*prev;
};
class number {
public:
Node* head;
number(); //konstruktor domyślny
~number(); //destruktor
void addNode(string str); //dodanie nowego wezla na poczatek liczby
void addNode(int str); //dodanie nowego wezla na poczatek liczby (z wartosci int)
number& operator+(number& licz); //operator dodawania
number& operator-(number& licz); //operator odejmowania
bool operator>(number& licz); //operator porównania (czy a > b)
bool operator<(number& licz); //operator porównania (a mniejsze od b)
bool operator==(number& licz); //operator porównania (czy a równe b)
number& operator=(const number& licz); //operator przypisania
number& operator-(); //operator zamiany liczby na przeciwną
friend istream& operator>>(istream& input,number& li); //operator pobierania liczby
friend ostream& operator<<(ostream& s,number& li); //operator wypisania
void validate(); //funkcja usuwajaca zera z poczatku liczby
number& operator/(number& licz); //dzielenie calkowitoliczbowe
number& operator*(number& licz); //mnożenie
void pushNode(int str);
};
number& number::operator/(number& licz)
{
/////////cases of dividing//////
if (this->head->value<0 && licz.head->value<0) {
return (-(*this))/(-licz);
}
if (this->head->value<0 && licz.head->value>0) {
return -((-(*this))/licz);
}
if (this->head->value>0 && licz.head->value<0) {
return -(*this/(-licz));
}
number tmp_this=*this;
number tmp_licz=licz;
number zero;
zero.addNode(0);
//dividing by zero//
if (licz==zero) {
cout<<"dividing by zero"<<endl;
number* t=new number;
t->addNode(0);
return *t;
}
//dividing zero by sth ///
if (*this==zero) {
number* t=new number;
t->addNode(0);
return *t;
}
number i,jeden;
i.addNode(0);
jeden.addNode(1);
if (licz == jeden) {
return *this;
}
/// here real mess start///
string pl="";
number* tmp=new number;
Node* p=this->head,*q=licz.head;
tmp->pushNode(q->value);
while (p && *tmp < licz) {
p=p->next;
tmp->pushNode(p->value);
}
number* wynik=new number;
wynik=tmp;
int j;
while (*wynik > zero || *wynik==zero) {
*wynik=*wynik-tmp_licz;
j++;
}
char* str;
sprintf(str, "%d", j);
///end od mess///
};
I'm writing a custom arithmetics for a big numbers class (unlimited lenghth of a single number)
Dividing using multiple decrementing numer A by B fails when A is much grater than B.
I'm trying to implement written division, but i find it too complicated in my situation.
I can't store numbers in string (it is the main limitation of the project), so i store them in groups of 4 digits in a list of int's.
I tried to treat it like the whole 4 digit structure is a single digit in popular written division, but i got lost during implementing, by overloading / operator.
I'd like to get a hint if I'm doing the last, main part of dividing correct? How can I improve the method if dividing in this class?
struct Node{
int value;
Node* next,*prev;
};
class number {
public:
Node* head;
number(); //konstruktor domyślny
~number(); //destruktor
void addNode(string str); //dodanie nowego wezla na poczatek liczby
void addNode(int str); //dodanie nowego wezla na poczatek liczby (z wartosci int)
number& operator+(number& licz); //operator dodawania
number& operator-(number& licz); //operator odejmowania
bool operator>(number& licz); //operator porównania (czy a > b)
bool operator<(number& licz); //operator porównania (a mniejsze od b)
bool operator==(number& licz); //operator porównania (czy a równe b)
number& operator=(const number& licz); //operator przypisania
number& operator-(); //operator zamiany liczby na przeciwną
friend istream& operator>>(istream& input,number& li); //operator pobierania liczby
friend ostream& operator<<(ostream& s,number& li); //operator wypisania
void validate(); //funkcja usuwajaca zera z poczatku liczby
number& operator/(number& licz); //dzielenie calkowitoliczbowe
number& operator*(number& licz); //mnożenie
void pushNode(int str);
};
number& number::operator/(number& licz)
{
/////////cases of dividing//////
if (this->head->value<0 && licz.head->value<0) {
return (-(*this))/(-licz);
}
if (this->head->value<0 && licz.head->value>0) {
return -((-(*this))/licz);
}
if (this->head->value>0 && licz.head->value<0) {
return -(*this/(-licz));
}
number tmp_this=*this;
number tmp_licz=licz;
number zero;
zero.addNode(0);
//dividing by zero//
if (licz==zero) {
cout<<"dividing by zero"<<endl;
number* t=new number;
t->addNode(0);
return *t;
}
//dividing zero by sth ///
if (*this==zero) {
number* t=new number;
t->addNode(0);
return *t;
}
number i,jeden;
i.addNode(0);
jeden.addNode(1);
if (licz == jeden) {
return *this;
}
/// here real mess start///
string pl="";
number* tmp=new number;
Node* p=this->head,*q=licz.head;
tmp->pushNode(q->value);
while (p && *tmp < licz) {
p=p->next;
tmp->pushNode(p->value);
}
number* wynik=new number;
wynik=tmp;
int j;
while (*wynik > zero || *wynik==zero) {
*wynik=*wynik-tmp_licz;
j++;
}
char* str;
sprintf(str, "%d", j);
///end od mess///
};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我想这里有一个问题,也没有问号。
您尝试同时解决两个复杂的任务(这可能会失败 - 或者已经失败)。拆分这两个任务:
为了存储“4字节数字”, std::vector 似乎更好。当将它们存储在列表节点中时,每个数字使用 4 个字节,而不是 8 个或更多字节。当数字变大(a += b)时, std::vector 可以增长,并且如果需要的话可以缩小。
对于算术,您还可以将加号/减号分开并首先对非负数进行运算。
加法、减法和乘法相对简单。对于除法,我必须看 Donald Knuth 的《计算机编程艺术》第 2 卷(半数值算法),并花了两周的时间来解决它。也许我在这一点上还不是特别擅长。
请考虑到,当 2 字节数相乘时,您会得到 4 字节数。否则整数溢出会破坏你的结果。另一种方法是除法。
如果您想查看我在同一教育任务上的结果,请在谷歌上搜索我的姓氏和“Ganzzahl”。但要注意,它没有经过严格的测试,用德语编写,而且自从我几年前编写以来,我不再认为它是编写良好的代码...
如果您正在寻找生产代码解决方案,请尝试使用像 GNU 这样的库改为多精度整数。
I suppose there is a question in here, also without a question mark.
You try to solve two complicated tasks at the same time (this will probably fail - or has failed already). Split these two tasks:
For storing the "4-byte-digits" a std::vector seems to be better. It uses 4 bytes per number instead for 8 or more, when storing them in list nodes. A std::vector can grow, when numbers get bigger (a += b) and shrink, if needed.
For arithmetic you can also separate the plus/minus sign and operate on non-negative numbers first.
Adding, subtracting and multiplying are relatively straight forward. For division I had to look on Donald Knuth's "The Art of Computer Programming" Vol.2 (seminumerical algorithms) and had two weeks to figure it out. Maybe I'm not especially good at this point.
Take into account, that you get 4 byte numbers when multiplying 2 byte numbers. Otherwise integer overflow will ruin your results. The other way around it is for dividing numbers.
If you want to look at my results on the same educational task, google for my last name and "Ganzzahl". But beware, it's not heavily tested, written in German, and since I wrote some years ago, I don't consider it well written code anymore...
If you look for a production code solution, try to get to some library like GNU multi precision integer instead.