所以我正在开发一个类“bignum”来处理任何大小的整数。问题是我做了两个不同的函数来乘以 bignums。一种是标准乘法,另一种是基于 karatsuba 算法。我有一个小程序来对我的实现进行测试,这样我就可以判断它是否工作。到目前为止,使用标准乘法,一切都运行得很好,但是当我切换到 Karatsuba 乘法时,一旦输入开始很长,我的程序就会因为堆栈溢出而因分段错误而崩溃。然而,这似乎不是条目有多大的问题,因为有更大的输入可以正确计算,尽管其中一些确实会崩溃。如果有人可以看一下并给我一些有关如何继续的线索,我将不胜感激。
Stack overflow in thread #1: can't grow stack to 0x1ffe801000
在这里,我发布了最小的可重现示例。我尽可能多地取出代码。
主要的:
#include "bignum.h"
int main()
{
bignum result;
while(cin >> result)
cout << result << endl;
return 0;
}
bignum.cc 类:
#include "bignum.h"
bignum abs(const bignum &n)
{
bignum c = n;
c.sign = 0;
return c;
}
void remove_zeros(bignum &n)
{
if(n == 0)
n = 0;
else if(n.digits[0] == 0 && n.size > 1)
{
size_t zeros = 1;
while(n.digits[zeros] == 0)
zeros++;
n.size -= zeros;
short_t *aux = new short_t[n.size];
for(size_t i = 0; i < n.size; i++)
aux[i] = n.digits[i + zeros];
delete[] n.digits;
n.digits = new short_t[n.size];
for(size_t i = 0; i < n.size; i++)
n.digits[i] = aux[i];
delete[] aux;
}
}
bool size_even(const bignum &n)
{
if(n.size % 2 || n.size == 1)
return false;
return true;
}
bignum sum(const bignum &a, const bignum &b, const short_t &s)
{
size_t size = 0;
size_t aux_a = 0;
size_t aux_b = 0;
if(a.size >= b.size)
{
size = a.size + 1;
aux_a = a.size - b.size;
}
else
{
size = b.size + 1;
aux_b = b.size - a.size;
}
bignum c(size);
c.sign = s;
for(size_t i = c.size - 1; i < c.size; i--)
{
if(i - aux_b - 1 < a.size)
c.digits[i] += a.digits[i - aux_b - 1];
if(i - aux_a - 1 < b.size)
c.digits[i] += b.digits[i - aux_a - 1];
if(c.digits[i] > 9)
{
c.digits[i] -= 10;
c.digits[i - 1]++;
}
}
remove_zeros(c);
return c;
}
bignum subtraction(const bignum &a, const bignum &b)
{
short_t bigger = 0;
short_t count = 0;
size_t size = 0;
size_t diff = 0;
short aux = 0;
size = max(a.size, b.size);
diff = size - min(a.size, b.size);
bignum c(size);
if(abs(a) == abs(b))
return c = 0;
else if(abs(b) > abs(a))
bigger++;
if(bigger && b.sign && !a.sign)
c.sign = 1;
else if(!bigger && a.sign && !b.sign)
c.sign = 1;
else if(bigger && !b.sign && !a.sign)
c.sign = 1;
else if(!bigger && a.sign && b.sign)
c.sign = 1;
for(size_t i = size - 1; i < size; i--)
{
if(bigger)
{
if(i - diff < a.size)
aux = b.digits[i] - a.digits[i - diff];
else
aux = b.digits[i];
}
else
{
if(i - diff < b.size)
aux = a.digits[i] - b.digits[i - diff];
else
aux = a.digits[i];
}
if(count)
{
aux--;
count--;
}
if(aux < 0)
{
aux += 10;
count++;
}
c.digits[i] = aux;
}
remove_zeros(c);
if(c == 0)
c.sign = 0;
return c;
}
bignum reduce(const bignum &n, const size_t &from, const size_t &to)
{
if(to <= from)
{
bignum c = 0;
return c;
}
else
{
bignum c(to - from);
for(size_t i = 0; i < c.size; i++)
{
if(from + i < to)
c.digits[i] = n.digits[from + i];
}
// En caso de que haya agarrado solo ceros
if(c.digits[0] == 0 && c.size != 1)
{
for(size_t i = 0; i < c.size; i++)
if(c.digits[i] != 0)
return c;
return c = 0;
}
return c;
}
}
bignum enlarge(const bignum &n, const size_t &zeros)
{
bignum c(n.size + zeros);
if(!zeros)
c = n;
else
{
for(size_t i = 0; i < n.size; i++)
c.digits[i] = n.digits[i];
}
return c;
}
void add_zeros(bignum &n, const ssize_t &zeros)
{
if(zeros > 0)
{
short_t *aux = new short_t[n.size];
for(size_t i = 0; i < n.size; i++)
aux[i] = n.digits[i];
delete[] n.digits;
n.digits = new short_t[n.size += zeros];
for(size_t i = 0; i < n.size; i++)
{
if(i < n.size - zeros)
n.digits[i] = aux[i];
else
n.digits[i] = 0;
}
delete[] aux;
}
else if(zeros < 0)
{
short_t *aux = new short_t[n.size + zeros];
for(size_t i = 0; i < n.size + zeros; i++)
aux[i] = n.digits[i];
delete[] n.digits;
n.digits = new short_t[n.size += zeros];
for(size_t i = 0; i < n.size; i++)
n.digits[i] = aux[i];
delete[] aux;
}
}
bignum karatsuba(const bignum &a, const bignum &b)
{
bignum a_ = abs(a);
bignum b_ = abs(b);
bignum c;
// Casos base
if(a_ == 0 || b_ == 0)
return c = 0;
if(a_.size < 2 || b_.size < 2)
{
c = mult_rec(a_, b_);
if(a.sign != b.sign)
c.sign = 1;
return c;
}
size_t diff = max(a_.size, b_.size) - min(a_.size, b_.size);
if(!diff)
{
if(!size_even(a_.size) && !size_even(b_.size))
{
add_zeros(a_, 1);
add_zeros(b_, 1);
diff += 2;
}
}
else if(a_.size > b_.size)
{
if(!size_even(a_.size))
{
add_zeros(a_, 1);
add_zeros(b_, diff + 1);
diff += 2;
}
else
add_zeros(b_, diff);
}
else if(b_.size > a_.size)
{
if(!size_even(b_.size))
{
add_zeros(b_, 1);
add_zeros(a_, diff + 1);
diff += 2;
}
else
add_zeros(a_, diff);
}
size_t n = a_.size;
size_t m = n / 2;
bignum x = karatsuba(reduce(a_, 0, m), reduce(b_, 0, m));
bignum y = karatsuba(reduce(a_, m, a_.size), reduce(b_, m, b_.size));
bignum z = karatsuba(reduce(a_, 0, m) + reduce(a_, m, a_.size),
reduce(b_, 0, m) + reduce(b_, m, b_.size)) - x - y;
add_zeros(x, n);
add_zeros(z, m);
c = x + y + z;
if(diff)
add_zeros(c, -diff);
if(a.sign != b.sign)
c.sign = 1;
return c;
}
bignum mult_rec(const bignum &a, const bignum &b)
{
bignum c;
if(a == 0 || b == 0)
return c = 0;
if(a == 1)
return c = b;
if(b == 1)
return c = a;
return c = mult_rec(a, b - 1) + a;
}
bignum division(const bignum &a, const bignum &b, bignum &remainder)
{
bignum c;
if(a == 0 || b > a)
return c = 0;
bignum aux = a - b;
c = 1;
while(1)
{
aux = aux - b;
if(aux.sign)
{
remainder = aux + b;
break;
}
c = c + 1;
}
remove_zeros(c);
return c;
}
bignum division_rec(const bignum &a, const bignum &b)
{
bignum remainder = 0;
if(a.size < (b.size + 2))
return division(a, b, remainder);
return division_rec(reduce(a, b.size + 1, a.size) + (enlarge(remainder, a.size - b.size - 1)), b)
+ enlarge(division(reduce(a, 0, b.size + 1), b,remainder), a.size - b.size - 1);
}
bignum::bignum()
{
digits = NULL;
size = 0;
sign = 0;
}
bignum::bignum(const size_t &s)
{
if(s <= 0)
{
digits = NULL;
size = 0;
sign = 0;
}
digits = new short_t[s];
size = s;
sign = 0;
for (size_t i = 0; i < size; i++)
digits[i] = 0;
}
bignum::bignum(const string &str, short_t s = 0)
{
string aux;
size = str.size();
digits = new short_t[size];
for(size_t i = 0; i < size; i++)
{
aux = str[i];
digits[i] = (short_t)stoi(aux);
}
sign = s;
}
bignum::bignum(const bignum &n)
{
if(!n.digits)
{
digits = NULL;
size = 0;
sign = 0;
}
else
{
digits = new short_t[n.size];
size = n.size;
sign = n.sign;
for(size_t i = 0; i < size; i++)
digits[i] = n.digits[i];
}
}
bignum::bignum(const int &n)
{
if(n < 0)
sign = 1;
else
sign = 0;
string str = to_string(n);
string aux;
size = str.size()-sign;
digits = new short_t[size];
for(size_t i = 0; i < size; i++)
{
aux = str[i + sign];
digits[i] = (short_t)stoi(aux);
}
}
bignum& bignum::operator = (const bignum &right)
{
if(&right != this)
{
delete[] digits;
if(!right.digits)
{
digits = NULL;
size = 0;
sign = 0;
}
else
{
digits = new short_t[right.size];
size = right.size;
sign = right.sign;
for(size_t i = 0; i < size; i++)
digits[i] = right.digits[i];
}
}
return *this;
}
bignum& bignum::operator = (const int &right)
{
bignum aux(to_string(right));
return *this = aux;
}
bignum::~bignum() {delete[] digits;}
bignum operator + (const bignum &a, const bignum &b)
{
if(!a.sign && !b.sign)
return sum(a, b, 0);
if(!a.sign && b.sign)
return subtraction(a, b);
if(a.sign && !b.sign)
return subtraction(a, b);
return sum(a, b, 1);
}
bignum operator + (const bignum &a, const int &n)
{
return a + bignum(to_string(n));
}
bignum operator - (const bignum &a, const bignum &b)
{
if(!a.sign && !b.sign)
return subtraction(a, b);
if(!a.sign && b.sign)
return sum(a, b, 0);
if(a.sign && !b.sign)
return sum(a, b, 1);
return subtraction(a, b);
}
bignum operator - (const bignum &a, const int &n)
{
return a - bignum(to_string(n));
}
bignum operator * (const bignum &a, const bignum &b)
{
return karatsuba(a, b);
}
bignum operator / (const bignum &a, const bignum &b)
{
bignum c;
if(b == 0)
return c;
if(a == 0 || abs(b) > abs(a))
return c = 0;
if(abs(a) == abs(b))
{
if(a.sign != b.sign)
return c = -1;
return c = 1;
}
if(abs(b) == 1)
{
c = abs(a);
if(a.sign != b.sign)
c.sign = 1;
return c;
}
c = division_rec(abs(a), abs(b));
if(a.sign != b.sign)
c.sign = 1;
return c;
}
ostream& operator << (ostream &os, bignum &n)
{
if(n.digits == NULL)
return os;
if(n.sign && n != 0)
os << "-";
for (size_t i = 0; i < n.size; i++)
os << n.digits[i];
delete[] n.digits;
n.digits = NULL;
return os;
}
istream& operator >> (istream &is, bignum &result)
{
stack<char> operations;
queue<string> output;
string input;
getline(is, input);
if(input.empty())
return is;
for(size_t i = 0; i < input.size(); i++)
{
if(isblank(input[i])){}
else if(isdigit(input[i]))
{
size_t pos = i++;
size_t len = 1;
while(isdigit(input[i]))
{
len++;
i++;
}
i--;
output.push(input.substr(pos, len));
}
else if(input[i] == '-')
{
size_t j = i;
while(j != 0 && isblank(input[--j])){}
if(isdigit(input[j]) || input[j] == ')')
{
if(!operations.empty())
{
while(operations.top() == '-' || operations.top() == '+' || operations.top() == '*' || operations.top() == '/')
output.push(string{operations.pull()});
}
operations.push(input[i]);
}
else
output.push(string{"s"});
}
else if(input[i] == '+')
{
size_t j = i;
while(j != 0 && isblank(input[--j])){}
if(isdigit(input[j]) || input[j] == ')')
{
if(!operations.empty())
{
while(operations.top() == '-' || operations.top() == '+' || operations.top() == '*' || operations.top() == '/')
output.push(string{operations.pull()});
}
operations.push(input[i]);
}
}
else if(input[i] == '*' || input[i] == '/')
{
if(!operations.empty())
{
while(operations.top() == '*' || operations.top() == '/')
output.push(string{operations.pull()});
}
operations.push(input[i]);
}
else if(input[i] == '(')
operations.push(input[i]);
else if(input[i] == ')')
{
if(operations.empty())
{
cout << "Syntax Error" << endl;
return is;
}
while(!operations.empty() && operations.top() != '(')
output.push(string{operations.pull()});
if(!operations.empty())
operations.pull();
else
{
cout << "Syntax Error" << endl;
return is;
}
}
}
if(!operations.empty())
{
if(operations.top() == '(' && output.empty())
{
cout << "Syntax Error" << endl;
return is;
}
else
{
if(output.empty())
{
cout << "Syntax Error" << endl;
return is;
}
else
{
while(!operations.empty())
output.push(string{operations.pull()});
}
}
}
string aux;
short_t sign = 0;
stack<bignum> numbers;
while(!output.empty())
{
aux = output.pull();
if(isdigit(aux[0]))
{
numbers.push(bignum(aux, sign));
if(sign)
sign--;
}
else if(aux[0] == 's')
sign++;
else if(numbers.length() < 2)
{
cout << "Syntax Error" << endl;
return is;
}
else if(aux[0] == '+')
{
result = numbers.pull();
result = numbers.pull() + result;
numbers.push(result);
}
else if(aux[0] == '-')
{
result = numbers.pull();
result = numbers.pull() - result;
numbers.push(result);
}
else if(aux[0] == '*')
{
result = numbers.pull();
bignum auxiliar = numbers.pull();
//result = numbers.pull() * result;
result = auxiliar * result;
numbers.push(result);
}
else if(aux[0] == '/')
{
result = numbers.pull();
result = numbers.pull() / result;
numbers.push(result);
}
}
if(!numbers.empty())
result = numbers.pull();
else
{
cout << "Syntax Error" << endl;
return is;
}
return is;
}
bool operator == (const bignum &a, const bignum &b)
{
if(a.size != b.size)
{
for(size_t i = 0; i < a.size; i++)
{
if(a.digits[i] != 0)
return false;
}
for(size_t i = 0; i < b.size; i++)
{
if(b.digits[i] != 0)
return false;
}
return true;
}
if(a.sign != b.sign)
return false;
for (size_t i = 0; i < a.size; i++)
{
if (a.digits[i] != b.digits[i])
return false;
}
return true;
}
bool operator == (const bignum &a, const int &b)
{
bignum c(to_string(b));
if(a == c)
return true;
return false;
}
bool operator != (const bignum &a, const bignum &b)
{
if(a == b)
return false;
return true;
}
bool operator != (const bignum &a, const int &n)
{
bignum c(to_string(n));
if(a != c)
return true;
return false;
}
bool operator > (const bignum &a, const bignum &b)
{
if(a.size < b.size)
return false;
if(a.size > b.size)
return true;
if(!a.sign && b.sign)
return true;
if(a.sign && !b.sign)
return false;
if(a == b)
return false;
for (size_t i = 0; i < a.size; i++)
{
if (a.digits[i] > b.digits[i])
return true;
else if(a.digits[i] < b.digits[i])
return false;
}
return false;
}
bool operator < (const bignum &a, const bignum &b)
{
if(a > b)
return false;
if(a == b)
return false;
return true;
}
bignum.h:
#include <iostream>
#include <cstring>
#include <string>
#include "queue.h"
#include "stack.h"
using namespace std;
class bignum
{
private:
short_t *digits;
short_t sign;
size_t size;
friend bignum abs(const bignum &);
friend void remove_zeros(bignum &);
friend void add_zeros(bignum &, const ssize_t &);
friend bool size_even(const bignum &);
friend bignum reduce(const bignum &, const size_t &, const size_t &);
friend bignum enlarge(const bignum &, const size_t &);
friend bignum sum(const bignum &, const bignum &, const short_t &);
friend bignum subtraction(const bignum &, const bignum &);
friend bignum karatsuba(const bignum &, const bignum &);
friend bignum mult_rec(const bignum &, const bignum &);
friend bignum division(const bignum &, const bignum &, bignum &);
friend bignum division_rec(const bignum &, const bignum &);
public:
bignum();
bignum(const size_t &);
bignum(const string &, short_t);
bignum(const bignum &);
bignum(const int &);
bignum& operator = (const bignum &);
bignum& operator = (const int &);
~bignum();
friend bignum operator+(const bignum &, const bignum &);
friend bignum operator+(const bignum &, const int &);
friend bignum operator-(const bignum &, const bignum &);
friend bignum operator-(const bignum &, const int &);
friend bignum operator*(const bignum &, const bignum &);
friend bignum operator/(const bignum &, const bignum &);
friend ostream& operator<<(ostream &, bignum &);
friend istream& operator>>(istream &, bignum &);
friend bool operator==(const bignum &, const bignum &);
friend bool operator==(const bignum &, const int &);
friend bool operator!=(const bignum &, const bignum &);
friend bool operator!=(const bignum &, const int &);
friend bool operator<(const bignum &, const bignum &);
friend bool operator>(const bignum &, const bignum &);
};
生成文件:
all: calc
calc: mre.o bignum.o
g++ -std=c++11 -Wall -pedantic -g3 mre.o bignum.o -o calc
mre.o: mre.cc bignum.h
g++ -std=c++11 -Wall -pedantic -g3 -c mre.cc
bignum.o: bignum.cc bignum.h stack.h queue.h debug.h
g++ -std=c++11 -Wall -pedantic -g3 -c bignum.cc
clean:
$(RM) calc *.o
我使用的其他一些库,queue.h:
#ifndef _QUEUE_H_
#define _QUEUE_H_
#include <cstdlib>
#include <iostream>
#include "debug.h"
#include "stack.h"
using namespace std;
typedef unsigned short short_t;
template <typename T>
class queue
{
public:
queue();
queue(const queue &);
queue &operator=(const queue &);
~queue();
T pull();
void pull(T &);
void push(const T &);
bool empty() const;
size_t length() const;
private:
stack<T> egress_;
stack<T> ingress_;
};
template <typename T>
queue<T>::queue() {}
template<typename T>
queue<T>::queue(const queue &q)
: egress_(q.egress_),
ingress_(q.ingress_)
{
}
template<typename T>
queue<T> &queue<T>::operator=(const queue<T> &rhs)
{
if (this != &rhs) {
egress_ = rhs.egress_;
ingress_ = rhs.ingress_;
}
return *this;
}
template<typename T>
queue<T>::~queue(){}
template<typename T>
T queue<T>::pull()
{
if (egress_.empty()) {
while (ingress_.empty() == false)
egress_.push(ingress_.pull());
}
return egress_.pull();
}
template<typename T>
void queue<T>::pull(T &top)
{
return this->pull();
}
template<typename T>
void queue<T>::push(const T &item)
{
ingress_.push(item);
}
template<typename T>
bool queue<T>::empty() const
{
return egress_.empty() && ingress_.empty() ? true : false;
}
template<typename T>
size_t queue<T>::length() const
{
return egress_.length() + ingress_.length();
}
#endif
堆栈.h:
#ifndef _STACK_H_
#define _STACK_H_
#include <iostream>
#include <cstdlib>
#include "debug.h"
using namespace std;
template <typename T>
class stack
{
public:
stack();
stack(size_t);
stack(const stack &);
stack &operator=(const stack &);
~stack();
T pull();
T top();
void pull(T &);
void push(const T &);
bool empty() const;
size_t length() const;
private:
void expand();
void contract();
size_t tos_;
size_t len_;
T *ptr_;
};
template<typename T>
stack<T>::stack()
: tos_(0),
len_(0),
ptr_(0)
{
}
template<typename T>
stack<T>::stack(size_t len)
: tos_(0),
len_(0),
ptr_(0)
{
ptr_ = new T[len_ = len];
}
template<typename T>
stack<T>::stack(const stack &st)
: tos_(0),
len_(0),
ptr_(0)
{
ptr_ = new T[len_ = st.tos_];
for (tos_ = 0; tos_ < st.tos_; ++tos_)
ptr_[tos_] = st.ptr_[tos_];
ASSERT(tos_ <= len_);
ASSERT(tos_ == st.tos_);
}
template<typename T>
stack<T> & stack<T>::operator=(const stack<T> &rhs)
{
if (this != &rhs) {
if (rhs.tos_ > len_) {
delete[] ptr_, len_ = 0;
ptr_ = new T[len_ = rhs.tos_];
}
for (tos_ = 0; tos_ < rhs.tos_; ++tos_)
ptr_[tos_] = rhs.ptr_[tos_];
}
ASSERT(tos_ <= len_);
ASSERT(tos_ == rhs.tos_);
return *this;
}
template<typename T>
stack<T>::~stack()
{
delete[] ptr_;
}
template<typename T>
T stack<T>::pull()
{
ASSERT(tos_ != 0);
ASSERT(tos_ <= len_);
ASSERT(ptr_ != NULL);
return ptr_[--tos_];
}
template<typename T>
void stack<T>::pull(T &top)
{
top = this->pull();
}
template<typename T>
T stack<T>::top()
{
if(tos_ > 0)
return ptr_[tos_ -1];
return 0;
}
template<typename T>
void stack<T>::push(const T &top)
{
if (tos_ >= len_)
expand();
ptr_[tos_++] = top;
}
template<typename T>
bool stack<T>::empty() const
{
return tos_ == 0 ? true : false;
}
template<typename T>
size_t stack<T>::length() const
{
return tos_;
}
template<typename T>
void stack<T>::expand()
{
size_t len;
size_t tos;
T *ptr = 0;
if (len_ != 0)
len = len_ << 1;
else
len = 1;
ptr = new T[len];
for (tos = 0; tos < tos_; ++tos)
ptr[tos] = ptr_[tos];
delete[] ptr_;
tos_ = tos;
len_ = len;
ptr_ = ptr;
ASSERT(tos_ < len_);
ASSERT(ptr_ != NULL);
}
template<typename T>
void stack<T>::contract()
{
std::abort();
}
#endif
调试.h:
#ifndef _DEBUG_H_
#define _DEBUG_H_
#ifdef DEBUG
#include <cstdlib>
#include <iostream>
#define ASSERT(expr) \
do { \
if (!(expr)) { \
std::cerr << "assertion " \
<< (#expr) \
<< " failed :-\\ {" \
<< __FUNCTION__ \
<< "() " \
<< __FILE__ \
<< ":" \
<< __LINE__ \
<< "}" \
<< std::endl; \
std::abort(); \
} \
} while (0)
#else
#define ASSERT(expr) do {} while (0)
#endif
#endif
最后但并非最不重要的一点是,破坏程序的输入:
((((4)-(5) (((((3+9-(4) (-1)))-((4)-1-(-4) 0)))-((6+5 (0 )+(-5)) ((-4)-(-7) (-7) (-8))))+((((8) (0) (0)+3)+((-3) +6 8+(6)))-0+(-3))) ((1 (-8) (-6)-(-6)) ((((-2) (-4)-2 (- 5))+(-2) (4))-(((3)-(5)-(-4)+(-1)) (2)+(-5)))))) (((( 6)-(4) (3)-(9))+(((((-4) (-2) 0-(-6)) 1+(-7))-(1+(-3) ( -7) (-9)))-((((-3)-8+1-(-8)) (0+(8)+(0)+(-4))) 1+7))) +1 (3))) ((-3)+(4) ((((3+0+(-3)+(-1))) (((-1) (-2)+((0)- (-3)+(8)+(-7)))+(((-3)+(3)+(6)-8)+(1) (6))))-(-4) 8)(((8)-(-8) (((0)+(-9)+((3)+(0) (9) (-1)))-((4-(-9) 0 2) -((-6) (-8)-(-7) (4)))))-(((((6)+7+(-3) 5) ((9)+(1)-3* (5)))-(((-2)-(-1)-4-0)+((8)-6-(-3) (-3))))+0-(5)))) ))-((((((((8) (7)-(2)-(-9))+((9) (-8) (4)-0)))-(((5)+ (4) (4)+(3)) ((8) (-1)+6+8)))-((((-1)-(-9)+(9) (0))-(0 -(-2)+(-2)+(-3)))+(0) 0))+(-7)+(2)) (((1-(-4)-(((2)- (-7)-(-9) (-3))-(-7) (4)))+(((5+(4)-1+(-2))+((4)-(-7 )+(-6)-5))-((-2)+6+(0)+(-4))))+((((8+(-5)-(1)+(0)) -((4)+(-2) (-6)-0)) ((-9) (6)-((-4) 3+(-7)+0)))+((((-8) )+(-9)-(-5) 0) ((-7)(5)-(2)-(-5)))-4+(-6)))))+((-9)+(-8)+(2) (-4)))-((( (((-2)-(0)+(-1) (-4)) ((((-1) (7)-1 (-1))+(-3) (4)) (8)- 5))-((-7) (-9)-(((5 (2) (-4)-2) (2*(-8) (0)-8))+(((5)+( -3) (-4) (-9)) ((-2)-(-2)-2+(-9))))))+7+(4))+((-9)+5- (3+0+(((((-1)+(-2) (8) (-9))-((-5)-(-4)-(-3)-3)) (((- 7)+(-1)+(-3)+(-3)) 0 (3)))-((((0) (7)-(8)-(0)) (6+(-9) -0+(4)))-(5) (6)))))))