Calculate the power of e (e^x), why n = 999? - c

Well, I was looking on the net for a code to calculate the power of e (e^x) and found a few good codes for that. Then I found the following code and just wants to know what the n = 999 part and n <= 100 part are supposed to do? I mean.. why n <= 100? why n = 999?
#include<stdio.h>
#define ACCURACY 0.0001
int main() {
int n, count;
float x, term, sum;
printf("\nEnter value of x :");
scanf("%f", &x);
n = term = sum = count = 1;
while (n <= 100) {
term = term * x / n;
sum = sum + term;
count = count + 1;
if (term < ACCURACY)
n = 999;
else
n = n + 1;
}
printf("\nTerms = %d Sum = %f", count, sum);
return 0;
}

It's just a sum of terms in a series.
The term < ACCURACY test just looks to see if the desired accuracy was reached. If not, it goes to the next term in the series. If yes, n = 999 just makes the loop end. You could put there break; with the same result.

Related

Swap number digit order by separate a number into arrays and then merge

I can't elaborate a program with arrays language C.
The console received 4 numbers. I want to change the first number digits and multiply with the other.
Example input: 1260
Desire output: Change 12 to 21 and them multiple by 60 -> so output will be 1260 (as 21 * 60)
This is my current code:
int main() {
int number, temp;
int newnumber[4];
int n = 3;
printf("put the number");
scanf("%d", &number);
do {
newnumber[n] = number % 10;
number = number / 10;
n--;
} while (n >= o);
temp = newnumber[1];
newnumber[1] = newnumber[2];
newnumber[2] = temp;
}
know how i do 21 multiply with 60?
If we look at your example:
1260 => change 2 with 1, and multiply 21 with 60.
The permutation in your main function is wrong, cause you changed numbers at the index 1 (second position) and 2 (third position).
Back to your question, you can get the result you're looking for by doing the oppisite of what you did to get the units, tens and hundreds...
int main() {
int number, temp1, temp2;
int newnumber[4];
int n = 3;
printf("put the number");
scanf("%d", &number);
do {
newnumber[n] = number % 10;
number = number / 10;
n--;
} while (n >= 0);
temp1 = newnumber[0];
newnumber[0] = newnumber[1];
newnumber[1] = temp1;
temp1 = newnumber[0] * 10;
temp1 += newnumber[1];
temp2 = newnumber[2] * 10;
temp2 += newnumber[3];
printf("%d", temp1 * temp2);
}
I would have go with slightly different approach: first separate the numbers. Then call function to change the number order.
If you always get numbers with 2 digit you can do this:
int first = number / 100;
int second = number % 100;
And a function to swap the digit:
function swapDigits(int num) {
int ans = 0;
while (num > 0) {
ans = ans * 10 + num % 10;
num /= 10;
}
return ans;
}
Now just do second * swapDigits(first) to get your result.
I'm not c expert so verify my code before use...
If your conditions always hold you can keep it simple and do something like this:
int main() {
int number;
int newnumber[4];
int n = 3;
printf("put the number");
scanf("%d", &number);
do {
newnumber[n] = number % 10;
number = number / 10;
n--;
} while (n >= 0);
printf("And the result: %d\n", (newnumber[1] * 10 + newnumber[0]) * (newnumber[2] * 10 + newnumber[3]));
}
Then you are not getting the individual digits, but pairs and the like. Just get the last two digits in one shot:
int rem = number % 100; /* last two digits */
number /= 100;
int msd = number % 10; /* next, third digit */
number /= 10;
int lsd = number % 10; /* most significant digit */
/* I don't assume you have more digits, because you are doing different
* operations with them, no pattern up to here, but you should continue
* your approach here. */
int out = (msd * 10 + lsd) * rem;
should give you a solution. No arrays needed.

Bug in While-Loop Keeps Counting Beyond Condition

For school I am to write a C program that takes some amount of cash and returns the smallest number of coins it would take to reach that amount. I don't know what I am doing wrong. I've been tweaking and trying all sorts of different things but I cannot seem to totally debug the program.
The program gives correct answers to some inputs but overstates the amount of coins needed for many inputs.
Here is what I have so far.
#include <stdio.h>
int main()
{
float cash;
int n;
int counter=0;
int quarters=0;
int dimes=0;
int nickels=0;
int pennies=0;
for (;;)
{
printf("Enter change amount: ");
scanf("%f",&cash);
if (cash > 0)
{
break;
}
}
n = cash * 100;
counter = 0;
while (n > 0)
{
while (n >= 25)
{
counter ++;
n = n - 25;
quarters ++;
printf("%i\n",n);
}
while (n >= 10 && n < 25)
{
counter ++;
n = n - 10;
dimes ++;
printf("%i\n",n);
}
while (n >= 5 && n < 10)
{
counter ++;
n = n - 1;
nickels++;
printf("%i\n",n);
}
while (n > 0 && n < 5)
{
counter ++;
n = n - 1;
pennies ++;
printf("%i\n",n);
}
}
printf("%d\n",counter + n);
printf("%i quarters, %i dimes, %i nickels, %i pennies\n",
quarters, dimes, nickels, pennies);
return 0;
}
I'm a bit surprised they're wanting you to use break to exit a loop, as you usually want loops to conclude "naturally" (and you usually save breaks for switch statements). Something like this should work, using integer division and the modulus operator (edit note: I'm using two ints instead of a single float because of inaccuracy with the latter. If someone more knowledgeable wants to show how to do it with float, would be interesting.):
#include <stdio.h>
int main() {
int dollar, cent;
int q = 0;
int d = 0;
int n = 0;
int p = 0;
int re;
printf("Enter amount: ");
scanf(" %d.%d", &dollar, &cent);
q = dollar * 4;
re = cent;
q = q + (re / 25);
re = re % 25;
d = re / 10;
re = re % 10;
n = re / 5;
re = re % 5;
p = re;
printf("q %d d %d n %d p %d\n", q, d, n, p);
return 0;
}
This approach also works if, for example, you're given the seconds and want to find the min:sec from that. If you're given 65 seconds, you do 65 / 60 for the minutes portion (which is 1), and the seconds portion is just the remainder after you divide by 60, or 65 % 60 (which is 5).
Here is a more complete answer that fits with the code that you gave us to start with. I changed the loops to subtraction/multiplication and fixed the bug where you were treating nickels as pennies. You don't need the counter variable anymore, but I left it in.
#include <stdio.h>
int main()
{
float cash;
int n;
int counter=0;
int quarters=0;
int dimes=0;
int nickels=0;
int pennies=0;
for (;;)
{
printf("Enter change amount: ");
scanf("%f",&cash);
if (cash > 0)
{
break;
}
}
n = cash * 100;
counter = 0;
if (n > 0)
{
quarters = (int)floor(n / 25);
n -= quarters*25;
printf( "%i\n", n );
dimes = (int)floor(n / 10);
n -= dimes*10;
printf("%i\n",n);
nickels = (int)floor(n / 5);
n -= nickels*5;
printf("%i\n",n);
pennies = n;
printf("%i\n",n);
}
printf("%i quarters, %i dimes, %i nickels, %i pennies\n",
quarters, dimes, nickels, pennies);
return 0;
}
First of all, try start with abstracting out how to handle one type of coin:
int coinsNeeded( int amount, int coinAmount )
{
return (int) floor( amount / coinAmount );
}
Then, handle each coin separately:
quarters = coinsNeeded( cash, 25 );
cash -= (quarters * 25);
Just repeat that for each type of coins you want to consider, and then print out the information at the end. There is some disagreement about whether you want to use floating points or not. Floating points do have rounding errors that you want to avoid when using money. what you actually need is a fixed point data type, but I digress. You can get close enough by doing it the way you're doing it (multiplying by 100 and just dealing with pennies).

coding e^x function using Taylor Series without using math.h and factorial function

I am making simple calculator and it is e^x function part.
it works for positive number, but it doesn't for negative x.
How can I make it works for negative x too?`
double calculateEx(double x) {
double beforeResult = 1, afterResult = 1, term = 1, error = 1, i = 1, j;
while (error > 0.001) {
afterResult = beforeResult;
for (j = 1; j <= i; j++) {
term *= x;
}
term /= fact(i);
afterResult += term;
error = (afterResult - beforeResult) / afterResult;
if (error < 0) error * -1;
error *= 100;
beforeResult = afterResult;
term = 1;
i++;
}
return beforeResult;
}
double fact (double num) {
int i, j;
double total = 1;
for (i = 2; i <= num; i++) {
total = total * i;
}
return total;
}
When computing exponent via Taylor serie
exp(x) = 1 + x / 1 + x**2/2! + ... + x**n/n!
you don't want any factorials, please, notice that if n-1th term is
t(n-1) = x**(n-1)/(n-1)!
then
t(n) = x**n/n! = t(n-1) * x / n;
That's why all you have to implement is:
double calculateEx(double x) {
double term = 1.0;
double result = term;
/*
the only trick is that term can be positive as well as negative;
we should either use abs in any implementation or putr two conditions
*/
for (int n = 1; term > 0.001 || term < -0.001; ++n) {
term = term * x / n;
result += term;
}
return result;
}
OK, as I wrote in a comment above, I'd use <math.h> if at all possible, but since you asked the question:
To make it work with negative numbers, if x is negative, consider what happens if you negate it.
You can get rid of the factorial function by storing a table of factorials. You won't need that many elements.

Calculate Factorial within a single "for" loop to calculate sum of series

It took me a while conceptual to grasp how to code a loop that would calculate a given series in which a factorial was used.
I coded it--then my teacher told us we had to use a single for loop. I can't seem to grasp how to do something like this. It doesn't make sense how you'd keep the running total of the products across several numbers.
Here is my code; which includes a nested for loop. I really appreciate any and all help.
int main() {
/*init variables*/
int N; //number of terms
float NUMER, DENOM = 1;
float FRAC, sum = 0, x;
/*asks user for value of N*/
printf("Input number of terms: ");
scanf("%i", &N);
/*asks user for value of x*/
printf("Input value of x: ");
scanf("%f", &x);
for (int n = 0; n <= N; n++) {
NUMER = (pow(x, n)); //calculates numerator
for (int fac = 1; fac <= n; fac++) { //calculates factorial using for loop
DENOM = n * fac;
}
if (DENOM <= 0)
printf("\n\nError, dividing by zero.\n\n"); //this is for debugging purposes; disregard
FRAC = NUMER / DENOM; //calculates fraction
sum += FRAC; //running sum of series
}
printf("\nSum of the series is %.1f\n\n", sum); //prints sum of series
return 0;
You want DENOM = n!, so you can just start with DENOM = 1
and update the value inside the loop:
DENOM = 1;
for (int n = 0; n <= N; n++) {
NUMER = (pow(x, n)); //calculates numerator
FRAC = NUMER / DENOM; //calculates fraction
sum += FRAC; //running sum of series
DENOM *= n+1;
}
Instead of computing x^n and n! each time through the outer loop, you can initialize
the quotient to 1.0 before the outer loop, then on each pass through the outer loop,
multiply by x/n to get the next term in the series. This will avoid the need
to call pow(x,n), and use an inner loop to calculate the factorial, each pass through
the outer loop.
If you think about what you would do if calculating a factorial by hand, I think you can figure out how to code this pretty easily.
Lets say you are trying to calculate 11!. Well, you would start at 11, and them multiply by 10. Now you have 110. Now multiply by 9. You have 990. Now multiply by 8...
As you can see, the 11, 10, 9, 8... series is what your for loop is going to be. Just keep your 'current answer' in a variable and keep multiplying it by the number provided by your for loop.
That seems...complicated. Terseness is or can be your friend :D
I don't think it needs to be much more complicated than:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char* argv[] )
{
double limit = 10 ; // how far do we want to go?
double x = 2 ; // some value for X
double xn = 1 ; // by definition, for all X, X^0 is 1
double nf = 1 ; // by convention, 0! is 1
double value = 0 ;
double sum = 0 ;
double n = 0 ;
while ( n < limit )
{
value = xn / nf ; // compute the next element of the series
sum += value ; // add that to the accumulator
xn *= x ; // compute the *next* value for X^n
nf *= (++n) ; // compute the *next* value for N!
}
return 0;
}
You get a more stable answer working the loop in reverse. Many infinite sums numerically come out better summing the smallest terms together first.
f(x,n) = x^0/0! + x^1/1! + x^2/2! + ... + x^n/n!
Let the sum be S(x,n) = x/n
Let the sum of the 2 last terms be S(x,n-1) = x/(n-1) + x/(n-1)*S(x,n)
Let the sum of the 3 last terms be S(x,n-2) = x/(n-2) + x/(n-2)*S(x,n-1)
...
Let the sum of the N last terms be S(x,1) = x/(1) + x/(1)*S(x,1)
double e(double x, unsigned n) {
double sum = 0.0;
while (n > 0) {
sum = x*(1 + sum)/n;
n--;
}
sum += 1.0; // The zero term
return sum;
}
Notice that even if n is large like 1000, and the mathematical answer < DBL_MAX, this loop does not run into floating point overflow so easily.
[edit] But if code must be done in a forward loop, the below calculates each term not as separate products that may overflow, but a unified computation.
double e_forward(double x, unsigned n) {
double sum = 1.0;
double term = 1.0;
for (unsigned i = 1; i <= n; i++) {
term *= x / i;
sum += term;
}
return sum;
}

Efficient way to find the sum of digits of an 8 digit number

I have to find the sum of the first 4 digits, the sum of the last 4 digits and compare them (of all the numbers betweem m and n). But when I submit my solution online there's a problem with the time limit.
Here's my code:
#include <stdio.h>
int main()
{
int M, N, res = 0, cnt, first4, second4, sum1, sum2;
scanf("%d", &M);
scanf("%d", &N);
for(cnt = M; cnt <= N; cnt++)
{
first4 = cnt % 10000;
sum1 = first4 % 10 + (first4 / 10) % 10 + (first4 / 100) % 10 + (first4 / 1000) % 10;
second4 = cnt / 10000;
sum2 = second4 % 10 + (second4 / 10) % 10 + (second4 / 100) % 10 + (second4 / 1000) % 10;
if(sum1 == sum2)
res++;
}
printf("%d", res);
return 0;
}
I'm trying to find a more efficient way to do this.
Finally, if you are still interested, there is a much faster way to do this.
Your task doesn't specifically require you to calculate the sums for all the numbers,
it only asks for the number of some special numbers.
In such cases optimization techniques like memoization or dynamic programming come really handy.
In this case, when you have the first four digits of some number (let them be 1234),
you calculate their sum (in this case 10) and you immediately know,
what is the sum of the other four digits supposed to be.
Any 4-digit number, that yields sum 10 can now be the other half to create a valid number.
Therefore total number of valid numbers beginning with 1234 is exactly the number of all four digit numbers that give the sum 10.
Now consider another number, say 3412. This number has also sum equal to 10,
therefore any right-side that completes 1234 also completes 3412.
What this means is that the number of valid numbers beginning with 3412 is the same
as the number of valid numbers beginning with 1234, which is in turn the same as the total number of valid numbers, where the first half yields the sum 10.
Therefore if we precompute for each i the number of four digit numbers
that yield the sum i, we would know for each first four digits the exact number of
combinations of last four digits that complete a valid number,
without having to iterate over all 10000 of them.
The following implementation of this algorithm
Precomputes number of different ending halves for each sum of the beginning half
Splits the [M,N] interval in three subintervals, because in the first and the last beginning not every ending is possible
This algorithm runs quadratically faster than the naive implementation (for sufficiently big N-M).
#include <string.h>
int sum_digits(int number) {
return number%10 + (number/10)%10 + (number/100)%10 + (number/1000)%10;
}
int count(int M, int N) {
if (M > N) return 0;
int ret = 0;
int tmp = 0;
// for each i from 0 to 36 precompute number of ways we can get this sum
// out of a four-digit number
int A[37];
memset(A, 0, 37*4);
for (int i = 0; i <= 9999; ++i) {
++A[sum_digits(i)];
}
// nearest multiple of 10000 greater than M
int near_M = ((M+9999)/10000)*10000;
// nearest multiple of 10000 less than N
int near_N = (N/10000)*10000;
// count all numbers up to first multiple of 10000
tmp = sum_digits(M/10000);
if (near_M <= N) {
for (int i = M; i < near_M; ++i) {
if (tmp == sum_digits(i % 10000)) {
++ret;
}
}
}
// count all numbers between the 10000 multiples, use the precomputed values
for (int i = near_M / 10000; i < near_N / 10000; ++i) {
ret += A[sum_digits(i)];
}
// count all numbers after the last multiple of 10000
tmp = sum_digits(N / 10000);
if (near_N >= M) {
for (int i = near_N; i <= N; ++i) {
if (tmp == sum_digits(i % 10000)) {
++ret;
}
}
}
// special case when there are no multiples of 10000 between M and N
if (near_M > near_N) {
for (int i = M; i <= N; ++i) {
if (sum_digits(i / 10000) == sum_digits(i % 10000)) {
++ret;
}
}
}
return ret;
}
EDIT: I fixed the bugs mentioned in the comments.
I don't know if this would be significantly faster or not, but you might try breaking the number into two 4 digit numbers, then use a table lookup to get the sums. That way there's only one division operation instead of eight.
You can pre-compute the table of 10000 sums so it gets compiled in so there's no runtime cost at all.
Another slightly more complicated, but probably much faster, approach that can be used is have a table or map of 10000 elements that's the reverse of the sum lookup table where you can map the sum to the set of four digit numbers that would produce that sum. That way, when you have to find the result for a particular range 10000 number range, it's a simple lookup on the sum of the most significant four digits. For example, to find the result for the range 12340000 - 12349999, you could use a binary search on the reverse lookup table to quickly find how many numbers in the range 0 - 9999 have the sum 10 (1 + 2 + 3 + 4).
Again - this reverse sum lookup table can be pre-computed and compiled in as a static array.
In this way, the results for complete 10000 number ranges are performed with a couple binary searches. Any partial ranges can also be handled with the reverse lookup table with slightly more complication due to having to ignore matches that are from out of the range of interest. But that complication only has to happen at most twice for your whole set of subranges.
This would reduce the complexity of the algorithm from O(N*N) to O(N log N) (I think).
update:
Here's some timings I got (Win32-x86, using VS 2013 (MSVC 12) with release build default options):
range range
start end count time
================================================
alg1(10000000, 99999999): 4379055, 1.854 seconds
alg2(10000000, 99999999): 4379055, 0.049 seconds
alg3(10000000, 99999999): 4379055, 0.001 seconds
with:
alg1() is the original code from the question
alg2() is my first cut suggestion (lookup precomputed sums)
alg3() is the second suggestion (binary search lookup of sum matches using a table sorted by sums)
I'm actually surprised at the difference between alg1() to alg2()
You are going about this the wrong way. A little bit of cleverness is worth a lot of horsepower. You should not be comparing the first and last four digits of every number.
First - notice that the first four digits will change very slowly - so for sure you can have a loop of 10000 of the last four digits without re-computing the first sum.
Second - the sum of digits repeats itself every 9th number (until you get overflow). This is the basis of the "number is divisible by 9 if sum of digits is divisible by 9". example:
1234 - sum = 10
1234 + 9 = 1243 - sum is still 10
What this means is that the following will work pretty well (pseudo code):
take first 4 digits of M, find sum (call it A)
find sum of last four digits of M (call it B)
subtract: C = (A - B)
If C < 9:
D = C%9
first valid number is [A][B+D]. Then step by 9, until...
You need to think a bit about the "until", and also about what to do when C >= 9. This means you need to find a zero in B and replace it with a 9, then repeat the above.
If you want to do nothing else, then see that you don't need to re-compute the sum of digits that did not change. In general when you add 1 to a number, the sum of digits increases by 1 (unless there is carry - then it decreases by 9; and that happens every 9th, 99th (twice -> sum drops by 18), 999th (drop by 27), etc.
I hope this helps you think about the problem differently.
I am going to try an approach which doesn't make use of the lookup table (even though I know that the second one should be faster) to investigate how much we can speedup just optimizing calculus. This algorithm can be used where stack is an important resource...
Let's work on the idea that divisions and modulus are slow, for example in cortex R4 a 32 bit division requires up to 16 loops while a multiplication can be done in a single loop, with older ARMs things can be even worse.
This basic idea will try to get rid of them using digit arrays instead of integers. To keep it simple let's show an implementation using printf before a pseudo optimized version.
void main() {
int count=0;
int nmax;
char num[9]={0};
int n;
printf( "Insert number1 ");
scanf( "%d", &nm );
printf( "Insert number2 ");
scanf( "%d", &nmax );
while( nm <= nmax ) {
int sumup=0, sumdown=0;
sprintf( num, "%d", nm );
for( n=0; n<4; n++ ) {
sumup += num[n] -'0'; // subtracting '0' is not necessary (see below)
sumdown += num[7-n]-'0'; // subtracting '0' is not necessary (see below)
}
if( sumup == sumdown ) {
/* whatever */
count++;
}
nm++;
}
}
You may want to check that the string is a valid number using strtol before calling the for loop and the length of the string using strlen. I set here fixed values as you required (I assume length always 8).
The downside of the shown algorithm is the sprintf for any loop that may do thing worse... So we apply two major changes
we use [0-9] instead of ['0';'9']
we drop the sprintf for a faster solution which takes in account that we need to format a digit string starting from the previous number (n-1)
Finally the pseudo optimized algorithm should look something like the one shown below in which all divisions and modules are removed (apart from the first number) and bytes are used instead of ASCII.
void pseudo_optimized() {
int count=0;
int nmax,nm;
char num[9]={0};
int sumup=0, sumdown=0;
int n,i;
printf( "Insert number1 ");
scanf( "%d", &nm );
printf( "Insert number2 ");
scanf( "%d", &nmax );
n = nm;
for( i=7; i>=0; i-- ) {
num[i]=n%10;
n/=10;
}
while( nm <= nmax ) {
sumup = num[0] + num[1] + num[2] + num[3];
sumdown = num[7] + num[6] + num[5] + num[4];
if( sumup == sumdown ) {
/* whatever */
count++;
}
nm++;
/* Following loop is a faster sprintf replacement and
* it will exit at the first value 9 times on 10
*/
for( i=7; i>=0; i-- ) {
if( num[i] == 9 ) {
num[i]=0;
} else {
num[i] += 1;
break;
}
}
}
}
Original algo on my vm 5.500000 s, this algo 0.950000 s tested for [00000000=>99999999]
The weak point of this algorithm is that it uses sum of digits (which are not necessary and a for...loop that can be unrolled.
* update *
further optimization. The sums of digits are not necessary.... thinking about it I could improve the algorithm in the following way:
int optimized() {
int nmax=99999999,
int nm=0;
clock_t time1, time2;
char num[9]={0};
int sumup=0, sumdown=0;
int n,i;
int count=0;
n = nm;
time1 = clock();
for( i=7; i>=0; i-- ) {
num[i]=n%10;
n/=10;
}
sumup = num[0] + num[1] + num[2] + num[3];
sumdown = num[7] + num[6] + num[5] + num[4];
while( nm <= nmax ) {
if( sumup == sumdown ) {
count++;
}
nm++;
for( i=7; i>=0; i-- ) {
if( num[i] == 9 ) {
num[i]=0;
if( i>3 )
sumdown-=9;
else
sumup-=9;
} else {
num[i] += 1;
if( i>3 )
sumdown++;
else
sumup++;
break;
}
}
}
time2 = clock();
printf( "Final-now %d %f\n", count, ((float)time2 - (float)time1) / 1000000);
return 0;
}
with this we arrive to 0.760000 s which is 3 times slower than the result achieved on the same machine using lookup tables.
* update* Optimized and unrolled:
int optimized_unrolled(int nm, int nmax) {
char num[9]={0};
int sumup=0, sumdown=0;
int n,i;
int count=0;
n = nm;
for( i=7; i>=0; i-- ) {
num[i]=n%10;
n/=10;
}
sumup = num[0] + num[1] + num[2] + num[3];
sumdown = num[7] + num[6] + num[5] + num[4];
while( nm <= nmax ) {
if( sumup == sumdown ) {
count++;
}
nm++;
if( num[7] == 9 ) {
num[7]=0;
if( num[6] == 9 ) {
num[6]=0;
if( num[5] == 9 ) {
num[5]=0;
if( num[4] == 9 ) {
num[4]=0;
sumdown=0;
if( num[3] == 9 ) {
num[3]=0;
if( num[2] == 9 ) {
num[2]=0;
if( num[1] == 9 ) {
num[1]=0;
num[0]++;
sumup-=26;
} else {
num[1]++;
sumup-=17;
}
} else {
num[2]++;
sumup-=8;
}
} else {
num[3]++;
sumup++;
}
} else {
num[4]++;
sumdown-=26;
}
} else {
num[5]++;
sumdown-=17;
}
} else {
num[6]++;
sumdown-=8;
}
} else {
num[7]++;
sumdown++;
}
}
return count;
}
Unrolling vectors improves the speed of about 50%. The algorithm costs now 0.36000 s, by the way it makes use of the stack a bit more than the previous solution (as some 'if' statements may result in a push, so it cannot be always used). The result is comparable with Alg2#Michael Burr on the same machine, [Alg3-Alg5]#Michael Burr are a lot faster where stack isn't a concern.
Note all test where performed on a intel VMS. I will try to run all those algos on a ARM device if I will have time.
#include <stdio.h>
int main(){
int M, N;
scanf("%d", &M);
scanf("%d", &N);
static int table[10000] = {0,1,2,3,4,5,6,7,8,9};
{
register int i=0,i1,i2,i3,i4;
for(i1=0;i1<10;++i1)
for(i2=0;i2<10;++i2)
for(i3=0;i3<10;++i3)
for(i4=0;i4<10;++i4)
table[i++]=table[i1]+table[i2]+table[i3]+table[i4];
}
register int cnt = M, second4 = M % 10000;
int res = 0, first4 = M / 10000, sum1=table[first4];
for(; cnt <= N; ++cnt){
if(sum1 == table[second4])
++res;
if(++second4>9999){
second4 -=10000;
if(++first4>9999)break;
sum1 = table[first4];
}
}
printf("%d", res);
return 0;
}
If you know that the numbers are fixed like that, then you can you substring functions to get the components and compare them. Otherwise, your modulator operations are contributing unnecessary time.
i found faster algorithm:
#include <stdio.h>
#include <ctime>
int main()
{
clock_t time1, time2;
int M, N, res = 0, cnt, first4, second4, sum1, sum2,last4_ofM,first4_ofM,last4_ofN,first4_ofN,j;
scanf("%d", &M);
scanf("%d", &N);
time1 = clock();
for(cnt = M; cnt <= N; cnt++)
{
first4 = cnt % 10000;
sum1 = first4 % 10 + (first4 / 10) % 10 + (first4 / 100) % 10 + (first4 / 1000) % 10;
second4 = cnt / 10000;
sum2 = second4 % 10 + (second4 / 10) % 10 + (second4 / 100) % 10 + (second4 / 1000) % 10;
if(sum1 == sum2)
res++;
}
time2 = clock();
printf("%d\n", res);
printf("first algorithm time: %f\n",((float)time2 - (float)time1) / 1000000.0F );
res=0;
time1 = clock();
first4_ofM = M / 10000;
last4_ofM = M % 10000;
first4_ofN = N / 10000;
last4_ofN = N % 10000;
for(int i = first4_ofM; i <= first4_ofN; i++)
{
sum1 = i % 10 + (i / 10) % 10 + (i / 100) % 10 + (i / 1000) % 10;
if ( i == first4_ofM )
j = last4_ofM;
else
j = 0;
while ( j <= 9999)
{
sum2 = j % 10 + (j / 10) % 10 + (j / 100) % 10 + (j / 1000) % 10;
if(sum1 == sum2)
res++;
if ( i == first4_ofN && j == last4_ofN ) break;
j++;
}
}
time2 = clock();
printf("%d\n", res);
printf("second algorithm time: %f\n",((float)time2 - (float)time1) / 1000000.0F );
return 0;
}
i just dont need to count sum of the first four digits all the time the number in changed. I need to count it one time per 10000 iterations. In worst case output is:
10000000
99999999
4379055
first algorithm time: 5.160000
4379055
second algorithm time: 2.240000
about half the better result.

Resources