From: http://zhedahht.blog.163.com/blog/static/254111742009101563242535/

Question: implement the function Double Power (double base, int exponent) to calculate the power of base's exponent. Overflow is not required.

Analysis: this seems simple. Some people may write the following code 30 seconds after they see the question:

double Power(double base, int exponent)

{

double result = 1.0;

for(int i = 1; i <= exponent; ++i)

result *= base;

return result;

}

The above code has at least one problem: Because the input exponent is an int value, it may be a positive number or a negative number. The above Code only takes into account the positive number of exponent. Next, we will change the code:

bool g_InvalidInput = false;

double Power(double base, int exponent)

{

g_InvalidInput = false;

if(IsZero(base) && exponent < 0) {

g_InvalidInput = true;

return 0.0;

}

unsigned int unsignedExponent = static_cast<unsigned int>(exponent);

if(exponent < 0)

unsignedExponent = static_cast<unsigned int>(-exponent);

double result = PowerWithUnsignedExponent(base, unsignedExponent);

if(exponent < 0)

result = 1.0 / result;

return result;

}

double PowerWithUnsignedExponent(double base, unsigned int exponent)

{

double result = 1.0;

for(int i = 1; i <= exponent; ++i)

result *= base;

return result;

}

The above code has been significantly improved compared with the previous Code, mainly reflected in: First, it considers that the exponent is negative. Second, it also deals with the case where base is 0 and the index exponent is negative. If no special processing is performed, the divisor may be 0. Here, a global variable is used to indicate invalid input. It should be pointed out that, since 0 ^ 0 is meaningless in mathematics, either 0 or 1 is acceptable, but it should be clearly stated in the document.

The code looks very strict logically. Does that mean there is no room for further improvement? Next we will discuss its performance: If the input index exponent is 32, We need to multiply at least 31 times in the loop in the powerwithunsignedexponent function according to the previous algorithm. However, we can consider another way of thinking: We need a number to the power of 32. If we already know its power of 16, so we only need to square it again on the basis of the power of 16. The power of 16 is the square of the power of 8. In this way, we only need to perform five multiplications to the power of 32: Square, 4 to the power of square, and 8 to the power of square on the power of four, calculate the power of 16 on the basis of the power of 8, and then the power of 32 on the basis of the power of 16.

32 is the integer power of 2. What if the input index exponent is not the integer power of 2? Let's change the number 6 for analysis. 6 is not the integer power of 2. However, we have noticed that 6 is equal to 2 + 4, so we can express the power of a number as the square of the number multiplied by its power 4. Therefore, the 6 power of a number requires three multiplication: the first is the square, the second is the 4 power on the basis of the square, and the last is the result of the square and the 4 power.

Now let's sum up the above ideas: the exponent is decomposed into one or several Integers of 2. We can use the continuous square method to obtain the exponential value with an integer of 2, and then multiply each of the preceding values to get the final result. So far, we have another question: how to break down an index into one or several two integers to the power. We will analyze the index as a binary number. For example, if the binary value of 6 is 110 and its 2nd bits and 3rd bits are 1, 6 = 2 ^ (2-1) + 2 ^ (3-1 ). That is to say, as long as the nth bit of it is 1, we will add the n-1 power of 2. Finally, we rewrite the powerwithunsignedexponent function based on the above ideas:

double PowerWithUnsignedExponent(double base, unsigned int exponent)

{

std::bitset<32> bits(exponent);

if(bits.none())

return 1.0;

int numberOf1 = bits.count();

double multiplication[32];

for(int i = 0; i < 32; ++i)

multiplication[i] = 1.0;

// if the i-th bit in exponent is 1, the i-th number in array multiplication is base ^ (2 ^ n)

int count = 0;

double power = 1.0;

for(int i = 0; i < 32 && count < numberOf1; ++i) {

if(i == 0)

power = base;

else

power = power * power;

if(bits.at(i)) {

multiplication[i] = power;

++count;

}

}

power = 1.0;

for(int i = 0; i < 32; ++i) {

if(bits.at(i))

power *= multiplication[i];

}

return power;

}

In the above Code, bitset in the standard function library of C ++ is used to represent the integer as its binary, increasing the readability of the Code. If the I-bit of the exponent is 1, save the base-based number in the I-digit of the array multiplication, and the I-level of 2 as the exponential value. Finally, we multiply the corresponding value of So bit 1 in the array to get the final result.

The code above requires us to determine whether multiplication is required based on each bit expressed in the binary base. Many users are not familiar with binary operations, so encoding may be difficult. We can consider another way of thinking: We need a number to the power of 32, if we already know its power of 16, so we only need to square it again on the basis of the power of 16. The power of 16 is the square of the power of 8. In this way, we only need to perform 5 multiplications to the power of 32: first obtain the square, then obtain the power of 4 on the basis of the square, and then obtain the power of 8 on the basis of the power of 4, calculate the power of 16 on the basis of the power of 8, and then the power of 32 on the basis of the power of 16.

That is to say, we can use the following formula to calculate the N power of:

This formula can be easily implemented using recursion. The new powerwithunsignedexponent code is as follows:

double PowerWithUnsignedExponent(double base, unsigned int exponent)

{

if(exponent == 0)

return 1;

if(exponent == 1)

return base;

double result = PowerWithUnsignedExponent(base, exponent >> 1);

result *= result;

if(exponent & 0x1 == 1)

result *= base;

return result;

}