Question

How do i determine the first n digits of an exponentiation (ab).

eg: for a = 12, b = 13 & n = 4, the first 4 digits are 1069.
Was it helpful?

Solution

Calculate ab by the following iterations:

a1 = a1,
a2 = a2,
...
ai = ai,
...
ab = ab

You have ai+1 = ai×a. Calcluate each ai not exactly. The thing is that the relative error of ab is less than n times relative error of a.
You want to get final relative error less than 10-n. Thus relative error on each step may be forumula. Remove last digits at each step.

For example, a=2, b=16, n=1. Final relative error is 10-n = 0.1. Relative error on each step is 0.1/16 > 0.001. Thus 3 digits is important on each step. If n = 2, you must save 4 digits. Common rule: save [n+log10 b] digits at each step.

2 (1), 4 (2), 8 (3), 16 (4), 32 (5), 64 (6), 128 (7), 256 (8), 512 (9), 1024 (10) → 102,
204 (11), 408 (12), 816 (13), 1632 (14) → 163, 326 (15), 652 (16).

Answer: 6.

This algorithm has a compexity of O(b). But it is easy to change it to get O(log b)

OTHER TIPS

Another solution, using log10:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, char **argv) {
       int a = 12;
       int b = 13;
       int n = 4;
       double x, y;

       x = b * log10(a);
       y = floor(pow(10, x - floor(x) + n - 1));
       printf("Result: %d\n", (int)y);

       return EXIT_SUCCESS;
}

n=9 k=3 n^n=387420489 and answer should be 387

enter image description here

this is the same thing, what @RC as done in his code. Thank you @RC i just showed the mathematic representation your code.

The easiest way programatically to do this is to use a stringstream to convert the result of the exponentation to a string and then take the n most significant (i.e. left) characters.

if you want a way without strings then this will work:

#include <iostream>
#include <sstream>
#include <math.h>

using namespace std;

double nDigExp( double a, double b, int n )
{
    stringstream ss;
    ss.setf( ios::fixed, ios::floatfield );
    ss << pow(a,b);
    double ret;
    for ( int i = 0; i < n; ++i) ret = (10 * ret) + (ss.get() - '0'); // Yeuch!!
    return ret;
}

int main( )
{
    double result = nDigExp( 12, 13, 4 );

    cout << result << endl;

    return 0;
}

But it's hardly the most elegent code. I'm sure you can improve it.

For this case - with magic numbers 12,13,4 in place:

#include <sstream>
#include <iomanip>
#include <cmath>

double a = 12;
int b = 13;
double result = std::pow(a,b);

std::stringstream strVal;
strVal.setf( ios::fixed, ios::floatfield );
strVal << result;
std::string output(strVal.str().substr(0,4));

output = "1069"

std::stringstream intStr(output);
int intVal;
intStr >> intVal;

intVal = 1069

EDIT: This should work for any combination where result does not overflow double.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top