Здравствуйте, lso, Вы писали:
lso>Стоит такая задача: необходимо написать пограмму на СИ++ умножения целых переменных произвольной длины с использованием операций сложения и сдвига.
lso>Порывшись в источниках на эту тему получил вот что:
Вспомнив, как умножать в столбик, написал:
Числа хранятся в виде двоичного массива произвольной длины младшими разрядами справа.
2All: Хочу услышать ваши замечания по использованию STL. В частности, как красиво заменить printf в CMultiplier::Print()
class CMultiplier
{
static void Print( int n ) { printf(".%02X", n); };
public:
typedef unsigned char byte;
typedef unsigned short word;
typedef vector < byte > ByteVector;
ByteVector Calculate( ByteVector& a, ByteVector& b )
{
ByteVector r;
r.resize( a.size() + b.size() );
int Idx = r.size() - 1;
int aIdx = a.size();
while( aIdx-- )
{
int rIdx = Idx--;
int bIdx = b.size();
while( bIdx-- )
{
word m = multiply( a[aIdx], b[bIdx] ) ;
int i = rIdx--;
do
{
m += r[ i ];
r[ i -- ] = byte( m );
} while( m >>= 8 );
}
};
return r;
};
ByteVector Calculate( long a, long b )
{
ByteVector aVec;
ByteVector bVec;
Init( aVec, a );
Init( bVec, b );
return Calculate( aVec, bVec );
};
void Print( ByteVector& V ){ for_each( V.begin(), V.end(), print );};
protected:
word multiply( word m1, byte m2 )
{
word a = m1;
word result = 0;
while( m2 )
{
result += ( ( m2 & 1 ) ? a : 0 );
a <<= 1;
m2 >>= 1;
};
return result;
};
void Init( ByteVector& V, unsigned int n )
{
while( n )
{
V.push_back( n & 0xFF );
n >>= 8;
};
reverse( V.begin(), V.end() );
};
};
А вот так использовать:
int main(int argc, char* argv[])
{
int m = 0xFFFFFFFF;
int n = 0xFFFFFFFF;
int x = 0xFFFFFFFF;
int y = 0xFFFFFFFF;
CMultiplier M;
M.Print( M.Calculate( CMultiplier().Calculate( x, y ), CMultiplier().Calculate( m, n ) ) );
return 0;
}