First of thanx to all that wasted their time for this
ggs wrote:Ok, so you are trying to calculate x^n, for when n >= 0, and an integer.(Didnt realise that before) That isnt very hard.
The recursive version looks like:
Code: Select all
double pow(double x, int n)
{
if (n == 0)
return 1;
else if ((n %2) == 0)
return pow( x, n/2) * pow( x^ n/2 );
else
return x * pow(x, n-1 );
}
Very good
, even if this algorithm isnt maximal optimized.
I already gave several hints what and where this algorithm could be improved.
Code: Select all
return pow( x, n/2) * pow( x^ n/2 );
instead of calculating pow( x, n/2) twice do the following:
Code: Select all
tmp = pow( x, n/2);
return tmp * tmp;
ggs wrote:
The iterative version:
Code: Select all
double pow(double x, int n)
{
if (n == 0)
return 1.0;
double res = x;
for ( ; n > 0; --n)
res = res * x;
return res;
}
Not very fast for large values of 'n' (there are much much faster versions), but it should do.
Also C/C++ cant actually store floatpoint numbers can go to a max of ~10^350.
Right. This one would work but it isnt exactly what the assigment was.
The recursiv version got a complexity of O(lb(n)) with n as the exponent.
Your iterativ version got a complexity of O(n) which is way worse than O(lb(n)).
Thus you wrote used a algorithm, that solves the problem but isnt efficient.
O(n) means it takes n steps to solve the problem thus n=16 means 16 steps. O(lb(n)) means it takes the logarithm of n to the base of 2 steps tp solve the problem. for n=16 this would mean 4 steps. for n=32768 this would mean 15 steps instead of 32768 for O(n). lb is an abbreviation for binary logarithm.
Mad wrote:I assume you want to keep all three cases as an optimization? This should work... No books used.
Code: Select all
double pow_i(double x, int n)
{
double answer;
int i;
if(n == 0) return 1;
answer = x;
for(i=1; 2*i <= n; i*=2)
answer *= answer;
for( ; i < n; ++i)
answer *=x;
return answer;
}
Same for this algorithm. Complexity of O(n).
Both codes also lack the ability to deal with 1000+ exponents
cause you developed them by using a real programming language with all its limits.
Thats why i developed my version on paper first. This one is it in pseudo code:
Code: Select all
FUN pow(base, exponent, result)
BEGIN
bitposition = most significant bit of exponent;
result = 1;
WHILE (bitposition of exponent>0) DO
result *= result;
IF (bit at bitposition is set) THEN
result *= base;
FI
bitposition >>= 1;
OD
END
As i said this code is needed for a later version of of calculating modular versions of large bases and large exponents.
Modular values are only usefull for integer values. Thus using floating point data taypes is not recommended.
After re-reading i realized, that i forgot to mention that the result has to be exact even if you have to calculate a number with 1000+ digits as base and 1000+ digits as exponent. Since i havent mentioned it i cannot blame you.
The following is the final version of the implemented function:
Code: Select all
/************************************************************
Name
powMod
Arguments:
n Exponent of Base this (this = x in the following)
k Modulo-Value
Returns:
n
(x) mod k
************************************************************/
BigInteger& BigInteger::powMod(BigInteger& n, BigInteger& k) {
BigInteger* retval = new BigInteger;
ELEMENT elempos = n.size-1;
ELEMENT bitpos = MOSTSIGBIT;
while((n.value[elempos] & bitpos) != bitpos) {
bitpos >>= 1;
}
(*retval) = 1;
while (elempos != 0xFFFFFFFF) {
(*retval) = retval->square() % k;
if((n.value[elempos] & bitpos) == bitpos) {
(*retval) = ((*retval) * (*this)) % k;
}
bitpos >>= 1;
if(bitpos == 0) {
bitpos = MOSTSIGBIT;
elempos--;
}
}
return retval->setTmp();
}
Today i looked the algorithm up in a book by Donald Knuth and another by Micheal Weslchenbach and realized that my algorithm is the same they propose
Ok...
After this one is solved is somebody interested in the rest of the assignment?