?? bignum.cpp
字號:
string BigInt::toString()
{
string s = ( sign >= 0 ? "" : "-" );
for( int i = size - 1; i >= 0; i-- )
s += ( digits[i] + '0' );
if( size == 0 ) s += '0';
return s;
}
void BigInt::print() //FIXME: make more efficient
{
cout << toString();
}
void BigInt::printWithCommas( ostream &out )
{
if( sign < 0 ) out.put( '-' );
for( int i = size - 1; i >= 0; i-- )
{
out.put( digits[i] + '0' );
if( !( i % 3 ) && i ) out.put( ',' );
}
if( size == 0 ) out.put( '0' );
}
void BigInt::grow()
{
char *olddigits = digits;
int oldCap = capacity;
capacity *= 2;
digits = new char[capacity];
memcpy( digits, olddigits, oldCap );
memset( digits + oldCap, 0, oldCap );
delete [] olddigits;
}
BigInt BigInt::operator++()
{
operator+=( 1 );
return *this;
}
BigInt BigInt::operator++( int )
{
return operator++();
}
BigInt BigInt::operator--()
{
operator-=( 1 );
return *this;
}
BigInt BigInt::operator--( int )
{
return operator--();
}
BigInt BigInt::operator-()
{
BigInt result( *this );
result.sign *= -1;
return result;
}
BigInt BigInt::operator+( int n )
{
BigInt result( *this );
result += n;
return result;
}
BigInt BigInt::operator+( BigInt n )
{
BigInt result( *this );
result += n;
return result;
}
BigInt &BigInt::operator+=( int n )
{
if( size == capacity ) grow();
int nsign = sig( n );
if( !nsign ) return *this;
if( !sign ) sign = nsign;
if( sign == nsign )
{
n *= nsign;
int carry = 0;
int i;
for( i = 0; n || carry; i++ )
{
int dig = n % 10;
int newdig = digits[i] + dig + carry;
digits[i] = newdig % 10;
carry = newdig / 10;
n /= 10;
}
size = max( i, size );
}
else operator-=( -n );
return *this;
}
BigInt &BigInt::operator+=( BigInt n )
{
int maxS = max( size, n.size ) + 1;
while( maxS >= capacity ) grow(); //FIXME: this is stupid
if( !n.sign ) return *this;
if( !sign ) sign = n.sign;
if( sign == n.sign )
{
int carry = 0;
int i;
for( i = 0; i < maxS - 1 || carry; i++ )
{
int newdig = carry;
if( i < size ) newdig += digits[i];
if( i < n.size ) newdig += n.digits[i];
digits[i] = newdig % 10;
carry = newdig / 10;
}
size = max( i, size );
}
else
{
n.sign *= -1;
operator-=( n );
n.sign *= -1;
}
return *this;
}
BigInt BigInt::operator-( int n )
{
BigInt result( *this );
result -= n;
return result;
}
BigInt BigInt::operator-( BigInt n )
{
BigInt result( *this );
result -= n;
return result;
}
BigInt &BigInt::operator-=( int n )
{
if( size == capacity ) grow();
int nsign = sig( n );
if( !nsign ) return *this;
if( !sign ) sign = 1;
if( sign == nsign )
{
BigInt bin = n;
if( sign >= 0 && *this < bin || sign < 0 && *this > bin )
{
// Subtracting a bigger number
operator=( toInt() - n );
return *this;
}
n *= nsign;
int carry = 0;
int i;
for( i = 0; n || carry; i++ )
{
int dig = n % 10;
int newdig = digits[i] - dig + carry;
if( newdig < 0 ) newdig += 10, carry = -1;
else carry = 0;
digits[i] = newdig;
n /= 10;
}
normalize();
}
else operator+=( -n );
return *this;
}
BigInt &BigInt::operator-=( BigInt n )
{
int maxS = max( size, n.size ) + 1;
while( maxS >= capacity ) grow(); //FIXME: this is stupid
if( !n.sign ) return *this;
if( !sign ) sign = 1;
if( sign == n.sign )
{
if( sign >= 0 && *this < n || sign < 0 && *this > n )
{
// Subtracting a bigger number
BigInt tmp = n;
tmp -= *this;
*this = tmp;
sign = -sign;
return *this;
}
int carry = 0;
int i;
for( i = 0; i < maxS - 1; i++ )
{
int newdig = carry;
if( i < size ) newdig += digits[i];
if( i < n.size ) newdig -= n.digits[i];
if( newdig < 0 ) newdig += 10, carry = -1;
else carry = 0;
digits[i] = newdig;
}
if( carry ) // Subtracted a bigger number, need to flip sign
{
if( i ) digits[0] = 10 - digits[0];
size = ( i ? 1 : 0 );
for( int j = 1; j < i; j++ )
{
digits[j] = 9 - digits[j];
if( digits[i] ) size = j + 1;
}
sign *= -1;
}
normalize();
}
else
{
n.sign *= -1;
operator+=( n );
n.sign *= -1;
}
return *this;
}
BigInt BigInt::operator*( int n )
{
BigInt result( 0, size + ( int )sizeof( n ) * 8 );
int nsign = sig( n );
n *= nsign;
result.sign = sign * nsign;
if( !result.sign ) return result;
int i, j;
for( i = 0; n; i++ )
{
int dig = n % 10;
if( dig )
{
int carry = 0;
for( j = 0; j < size || carry; j++ )
{
int newDig = result.digits[i + j] + ( j < size ? dig * digits[j] : 0 ) + carry;
result.digits[i + j] = newDig % 10;
carry = newDig / 10;
}
}
n /= 10;
}
result.size = i + j - 1;
return result;
}
BigInt BigInt::operator*( BigInt n )
{
BigInt result( 0, size + n.size );
result.sign = sign * n.sign;
if( !result.sign ) return result;
int i, j;
for( i = 0; i < n.size; i++ )
{
if( n.digits[i] )
{
int carry = 0;
for( j = 0; j < size || carry; j++ )
{
int newDig =
result.digits[i + j] +
( j < size ? n.digits[i] * digits[j] : 0 ) +
carry;
result.digits[i + j] = newDig % 10;
carry = newDig / 10;
}
}
}
result.size = i + j - 1;
return result;
}
void BigInt::operator*=( int n )
{
operator=( operator*( n ) );
}
void BigInt::operator*=( BigInt n )
{
operator=( operator*( n ) );
}
BigInt BigInt::operator/( int n )
{
if( !n ) n /= n; //XXX: force a crash
BigInt result( *this );
result /= n;
return result;
}
BigInt BigInt::operator/( BigInt n )
{
if( !n ) n.size /= n.size; //XXX: force a crash
BigInt result( *this );
result /= n;
return result;
}
void BigInt::operator/=( int n )
{
divide( n );
}
void BigInt::operator/=( BigInt n )
{
divide( n );
}
int BigInt::operator%( int n )
{
BigInt tmp( *this );
return tmp.divide( n );
}
void BigInt::operator%=( int n )
{
operator=( divide( n ) );
}
BigInt BigInt::operator%( BigInt n )
{
BigInt tmp( *this );
return tmp.divide( n );
}
void BigInt::operator%=( BigInt n )
{
operator=( divide( n ) );
}
int BigInt::divide( int n )
{
if( !n ) n /= n; //XXX: force a crash
int nsign = sig( n );
n *= nsign;
if( !sign ) return 0;
sign *= nsign;
int tmp = 0;
for( int i = size - 1; i >= 0; i-- )
{
tmp *= 10;
tmp += digits[i];
digits[i] = tmp / n;
tmp -= digits[i] * n;
}
normalize();
return tmp;
}
BigInt BigInt::divide( BigInt n )
{
if( !n ) n.size /= n.size; //XXX: force a crash
if( !sign ) return 0;
sign *= n.sign;
int oldSign = n.sign;
n.sign = 1;
BigInt tmp( 0, size );
for( int i = size - 1; i >= 0; i-- )
{
tmp *= 10;
tmp += digits[i];
digits[i] = 0;
while( tmp >= n ) { tmp -= n; digits[i]++; }
}
normalize();
n.sign = oldSign;
return tmp;
}
// This is only exact to the first 15 or so digits, but it is
// never an over-estimate
BigInt BigInt::operator*( long double n )
{
// the number of digits after the decimal point to use
int DIGS_AFTER_DOT = 15;
int nsign = sig( n );
n *= nsign;
int ndigs = n >= 1 ? ( int )log10( n ) + 1 : 0;
BigInt result( 0, size + ndigs );
result.sign = sign * nsign;
if( !result.sign ) return result;
if( n >= 1 ) for( int i = 0; i < ndigs; i++ ) n /= 10;
result.size = 0;
char afterDot[DIGS_AFTER_DOT + 1];
memset( afterDot, 0, sizeof( afterDot ) );
// Keep going until the DIGS_AFTER_DOT'th digit after the decimal point
for( int i = ndigs - 1; i >= -DIGS_AFTER_DOT; i-- )
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -