Длинная целочисленная арифметика на динамических массивах
Необходимо реализовать основные операции над длинными числами. Сами числа представить динамическими массивами цифр.
Листинг C++
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
#define forp(i, a, b, c) for (i = (a); (c) > 0 ? i <= (b) : i >= (b); i += (c))
#define forn(i, n) forp (i, 0, (n) - 1, 1)
#define form(i, n) forp (i, (n) - 1, 0, - 1)
#define forv(it, v) for (it = (v).begin (); it != (v).end (); ++ it)
#define uint long long
//--------------------- Defines ------------------------------------------------
#define sint int
#define vsint vector < sint >
#define sz size ()
#define at(v, i) (0 <= (i) && (i) < (v).size () ? v[i] : 0)
#define erase_null(v) while ((v).size () > 1 && (v).back () == 0) (v).pop_back ();
#define next_mod(v, i) if (0 <= (i) + 1 && (i) + 1 < (v).size ()) \
{\
v[(i) + 1] += v[(i)] / 10;\
v[(i)] %= 10; \
}
//--------------------- Shifts, Compare ----------------------------------------
vsint shift_left (vsint s, int k)
{
if (k <= 0) return s;
s.insert (s.begin (), k, 0);
return s;
}
vsint shift_right (vsint s, int k)
{
if (k <= 0) return s;
s.erase (s.begin (), s.begin () + min (k, (int)s.sz));
return s;
}
int cmp (vsint &a, vsint &b)
{
for (int i = max (a.sz, b.sz) + 1; i >= 0; -- i)
{
if (at (a, i) > at (b, i)) return 1;
if (at (a, i) < at (b, i)) return - 1;
}
return 0;
}
//--------------------- Add, Sub, Mul, Div -------------------------------------
vsint add (vsint &a, vsint &b)
{
vsint c (max (a.sz, b.sz) + 1, 0);
for (int i = 0; i < c.sz - 1; ++ i)
{
c[i] += at (a, i) + at (b, i);
next_mod (c, i);
}
erase_null (c);
return c;
}
vsint sub (vsint &a, vsint &b)
{
vsint c (a.sz, 0);
for (int i = 0; i < c.sz; ++ i)
{
c[i] += at (a, i) - at (b, i);
if (c[i] < 0 && i + 1 < c.sz)
{
c[i] += 10;
-- c[i + 1];
}
}
erase_null (c);
return c;
}
void sub_from (vsint &a, vsint &b)
{
for (int i = 0; i < a.sz; ++ i)
{
a[i] -= at (b, i);
if (a[i] < 0 && i + 1 < a.sz)
{
a[i] += 10;
-- a[i + 1];
}
}
erase_null (a);
}
vsint mul (vsint &a, vsint &b)
{
vsint c (a.sz + b.sz + 2, 0);
for (int i = 0; i < a.sz; ++ i)
if (a[i])
for (int j = 0; j < b.sz; ++ j)
if (b[j])
{
c[i + j] += a[i] * b[j];
next_mod (c, i + j);
}
for (int i = 0; i < c.sz; ++ i)
next_mod (c, i);
erase_null (c);
return c;
}
vsint div (vsint &a, vsint &b, vsint &r)
{
r.assign (1, 0);
vsint s (a.sz, 0);
for (int i = a.sz - 1; i >= 0; -- i)
{
r.insert (r.begin (), a[i]);
while (cmp (r, b) >= 0)
{
++ s[i];
sub_from (r, b);
}
}
erase_null (s);
erase_null (r);
return s;
}
//--------------------- Algo ---------------------------------------------------
vsint sqrt (vsint &a)
{
int n = (a.size () + 1) / 2;
vsint x (n, 0);
for (int i = n - 1; i >= 0; -- i)
for (x[i] = 9; x[i] > 0; -- x[i])
{
vsint xx = mul (x, x);
if (cmp (xx, a) <= 0)
break;
}
return x;
}
//---------------------- BigInteger --------------------------------------------
class binteger
{
public:
vsint a;
binteger ();
binteger (int x);
binteger (string s);
string tostr ();
friend int cmp (binteger a, binteger b);
friend binteger operator + (binteger a, binteger b);
friend binteger operator - (binteger a, binteger b);
friend binteger operator * (binteger a, binteger b);
friend binteger operator / (binteger a, binteger b);
friend binteger operator % (binteger a, binteger b);
friend binteger operator >> (binteger a, int k);
friend binteger operator << (binteger a, int k);
};
binteger :: binteger ()
{
a = vsint (1, 0);
}
binteger :: binteger (int x)
{
do
{
a.push_back (x % 10);
x /= 10;
}
while (x);
}
binteger :: binteger (string s)
{
a = vsint (s.sz, 0);
for (int i = s.sz - 1; i >= 0; -- i)
a[a.sz - i - 1] = s[i] - '0';
}
string binteger :: tostr ()
{
string s = "";
for (int i = a.sz - 1; i >= 0; -- i)
s += a[i] + '0';
return s;
}
int cmp (binteger a, binteger b)
{
return cmp (a.a, b.a);
}
binteger operator + (binteger a, binteger b)
{
binteger c;
c.a = add (a.a, b.a);
return c;
}
binteger operator - (binteger a, binteger b)
{
binteger c;
c.a = sub (a.a, b.a);
return c;
}
binteger operator * (binteger a, binteger b)
{
binteger c;
c.a = mul (a.a, b.a);
return c;
}
binteger operator / (binteger a, binteger b)
{
binteger c;
vsint r;
c.a = div (a.a, b.a, r);
return c;
}
binteger operator % (binteger a, binteger b)
{
binteger c;
vsint r;
div (a.a, b.a, r);
c.a = r;
return c;
}
binteger operator >> (binteger a, int k)
{
binteger c;
c.a = shift_right (a.a, k);
return c;
}
binteger operator << (binteger a, int k)
{
binteger c;
c.a = shift_left (a.a, k);
return c;
}
18:47
12.07.2010
По всем вопросам обращаться: rumterg@gmail.com