I am trying to code the summation of the following series:
I can't figure out how to alternate the sign from "-" to "+" to "-" and so on....
Here is my code:
#include<stdio.h>
int main()
{
int i=1,n;
float sum,num,den;
den=2;
sum=0;
printf("Enter number of terms for summation: ");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
num=i*(i+1);
den=den*(i+2);
sum+=num/den;
}
printf("%f",sum);
}
Start a variable at 1.
int coeff = +1;
then:
sum += coeff * num/den;
coeff *= -1; // Toggles -1 to +1 and back to -1 each loop.
When coeff is +1, then the expression is +1 * -1, which results in -1.
When coeff is -1, then the expression is -1 * -1, which results in +1.
the variable keeps toggling back-n-forth between +1 and -1.
Let’s discuss the methods proposed in comments and other answers in descending order of nominal burden. (By “nominal burden,” I meant what the code literally says to calculate, disregarding potential compiler optimization.)
sum+=pow(-1,i)*num/den. This calls pow, which is a complicated routine. This solution involves a function call and branching through the various special cases that pow must handle.
if ((i & 1) == 0) num = -num;. This involves testing, comparing, branching, negating, and assignment. For hardware design reasons, branching may impair performance.
int coeff = +1;, sum += coeff * num/den;, and coeff *= -1;. Okay, now we are on track. We have added just one variable and two multiplications. The latter does not even have to be a multiplication; it could be just coeff = -coeff;.
Having learned from those, can we solve it any more simply? Yes, we make a simple change, from:
den=den*(i+2);
to:
den=-den*(i+2);
Then den will flip between positive and negative each iteration, with just a single negation. However, we do need to start den with a negative value; den = -2;.
But then, consider this:
den = den*(-2-i);
Although this involves more characters changed in the source code, it might not be any more work. i+2 may be calculated by taking 2 and adding i, whereas -2-i may be calculated by taking −2 and subtracting i, the same amount of work.
Thus, you can make your program work for alternating signs without any more nominal work than the unchanging sign version.
int main()
{
int i=1,n, sign = 1;
float sum,num,den;
den=2;
sum=0;
printf("Enter number of terms for summation: ");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
num=i*(i+1);
den=den*(i+2);
sum+=sign * num/den;
sign *= -1;
}
printf("%f",sum);
}
With x = i % 2 alternating between 0 and 1, you have two equations in two variables:
+1 = A * 0 + B
-1 = A * 1 + B
From which you can quickly infer:
B = 1
A = -2
So what you can do is:
const int A = -2;
const int B = 1;
...
for (i = 0; i < n; i++)
{
int x = i % 2;
int y = A * x + B;
...
sum+=y*num/den;
}
Related
The program is to find the number of digits in a factorial of a number
#include <stdio.h>
#include <math.h>
int main()
{
int n = 0 , i , count = 0 , dig ;
double sum = 0, fact;
scanf("%d" , &n );
for(i=1;i<=n;i++)
{
sum = sum + log(i);
}
fact = (exp(sum));
while(fact!=0)
{
dig = ((int)fact%10);
count++;
fact = floor(fact/10);
}
printf("%d\n",count);
return 0;
}
Feel free to comment on making improvements on this code since I don't have a broad experience in Coding yet.
The reason your code is taking so long is that once n reaches about 180, the value of fact becomes too large to hold in a double-precision floating point variable. When you execute this line:
fact = (exp(sum));
you're basically setting fact to a value of infinity. As a result, the following while() loop never terminates.
There's also not much point calculating logarithms in your code. It will only slow things down. Just calculate the factorial in a double variable and reset it whenever it gets too large. Like this, for example:
int factorial_digit_count(int n) {
int i, nd=1;
double f = 1.0;
for (i=2; i<=n; i++) {
f *= i;
if (f > 1.0E+100) {
f /= 1.0E+100;
nd += 100;
}
}
while (f > 1.0E+10) {
f /= 1.0E+10;
nd += 10;
}
while (f >= 10.0) {
f /= 10.0;
nd++;
}
return nd;
}
Assuming you don't want to use any mathematical calculation but want to "brute force" your way through - this would how I would shorten your run time (and mostly clean up you code).
#include <stdio.h>
#include <math.h>
int main()
{
int n, fact = 1;
scanf("%d" , &n );
for (int i = 1; i < n; i++)
fact *= i;
int sum = 0;
while (fact != 0)
{
fact /= 10;
sum++
}
printf("%d\n",count);
return 0;
}
Hopefully this answers your question, good luck!
There is a simple relationship between the base b logarithm of a number and the base b representation of that number:
len(repr(x, b)) = 1 + floor(log(x, b))
In particular, in base 10, the number of digits in x is 1 + floor(log10(x)). (To see why that's the case, look at the result of that formula for powers of 10.)
Now, the logarithm of a×b is the sum of the logarithms of a and b. So the logarithm of n! is simply the sum of the logarithms of the integers from 1 to n. If we do that computation in base 10, then we can easily extract the length of the decimal expansion of n!.
In other words, if you sum the log10 of each value instead of the log, then you can get rid of:
fact = (exp(sum));
and
while(fact!=0)
{
dig = ((int)fact%10);
count++;
fact = floor(fact/10);
}
and just output 1 + floor(sum).
In theory, that could suffer from a round-off error. However, you'd need to do an awful lot of logarithms in order for the error term to propagate enough to create an error in the computation. (Not to say it can't happen. But if it happens, n is a very big number indeed.)
I am working on a project that requires me to find largest n such that x^n<=y where x and y are provided. I am using the gmp library and working with huge numbers in c.
Constraints:
x>=1 &
y>=1
Using the first approach that came into my mind, it took me around 5 secs to find n when x=12 and y = 411^20000 i.e,
int n=0;
int x=12;
int y=100;
int temp;
int answer;
while(1)
{
temp = pow(x,n);
if(temp>y)
{
answer = n-1;
return(0);
}
n++;
}
Note: Not actual code. Didn't want to complicate things with gmp syntax
Is there a faster algorithm?
Entire code:
https://pastebin.com/J1vbmEbK
If gmp library contains logarithm function, use it
result = Floor(log(y)/log(x))
Otherwise you can exploit binary search - square x (x, x^2, x^4, x^8) while possible, then diminish power step
Quick and dirty implementation for checking with usual numbers
returns 24 for x = 2; y = 31415926.0;
(same as Floor(ln(y)/ln(x))
int FindXPower(double x, double y)
{
int Powers[64];
double t, s, next;
int ix;
//exponential search phase
ix = 0;
t = x;
while (t <= y)
{
Powers[ix++] = t; //remember them to use later
t = t * t;
};
//now powers contain [x,x^2,x^4,x^8,x^16...]
ix--;
int Result = 1 << ix; // 2^lastindex: 1,2,4,8,16,32...
//binary search phase
s = Powers[ix--]; //max value after squaring
while ((s < y) && (ix >= 0))
{
t = Powers[ix];
next = s * t;
while (next < y)
{
s = next;
next = next * t;
Result = Result + (1<<ix);
}
ix--;
};
return Result;
}
Instead of linearly decreasing n you could search for the correct value by dichotomy.
Define two variables: n_low and n_high with the invariant that at any moment in time x^n_high is strictly greater than y and x^n_low is less than or equal to y.
At each iteration, compute the value of m which halves the distance between n_high and n_low.
Then compare x^m with y. If it is strictly greated, then assign: n_high = m else assign n_low = m. When n_low+1==n_high the value of n_low is the value you're looking for.
I assume you're working with arbitrary-precision integers (GMP also supports arbitrary-precision floating point).
Convert the bigints to floating-point. This will incur rounding errors.
Estimate the result computing n_est = floor(log(y_float) / log(x_float)).
The actual n is either n_est - 1, n_est, or n_est + 1 which can be checked easily.
First of all, I searched and all questions I found are similar but not exactly this one.
This is my first post here, I'm a beginner in programming and currently learning to code in C.
Been struggling with this code for about 5 hours now.
The question is create a program in C, using only loops (and not using pow(), using stdio.h library only).
The question is to get the user to give you two numbers - X and N
the program will print The result of the following equation:
1+2x+3x^2+4x^3+....+nx^(n-1)
For example for the input of - X=2 N=3
1*2^0 + 2*2^1 + 3*2^2
What the program will print is "17"
This is my attempt so far, I got to the Power function but I cant find a way to incorporate into the programm itself.
#include <stdio.h>
int main(void)
{
int i, j=0, b = 0;
float x, n;
double sum = 0, sumt=0;
do{
printf("Please enter two numbers \n");
flushall;
scanf("%f %f", &n, &x);
} while (x <= 0);
for (i = 1; i <= n; i++){
sum = x*x;
}
sumt += sum;
printf("%f", sum);
}
Instead of trying to create an implementation of pow, you will need to take advantage of the relationship between the terms of the expression.
The n-th term is nx^(n-1). The n-1-the term is (n-1)x^(n-2).
If we denote the n-th term as T(n) and denote the n-1-th term as T(n-1),
T(n) = T(n-1)*x*n/(n-1)
Given the starting value of the first term,
T(1) = 1
you can compute the subsequent terms using the above formula.
The following code should work.
// Initialize the values for N=1
term = 1;
sum = 1;
// Iterate starting from 2
for (i = 2; i <= n; i++){
term *= x*i/(i-1);
sum += term;
}
The working Program based on the tips given by the almighty #R_Sahu (And others ;D)
**
#include <stdio.h>
int main(void)
{
int i, j = 0, c = 0;
float x, n, b = 0;
double term, sum;
do {
printf("Enter Two Numbers\n");
flushall;
scanf("%f%f", &n, &x);
} while (x < 0);
for (i = 2; i < n + 2; i++)
{
term = 1;
sum = 1;
for (i = 2; i <= n; i++){
term *= x*i / (i - 1);
sum += term;
}
}
printf("The answer is %.lf ", sum);
}
I will not give you the code, but the reasoning you should follow
First you have to somehow get the data from the user (as a parameter, from stdio... whatever)
x = getFromUser
n = getFromUser
You will then need to init a temporary result
result = 0
How many times do you have to add? -> Exactly n times
for(ii=0;ii<n;ii++) {
result = result + pow((ii*x),(ii-1)) //There is something missing here, I'll let you guess what
}
But wait; you cannot use pow. So you have to program it by yourself (I guess that's the idea of the exercise)
then you need a function, and it has to return an int (actually, it may return even irrational numbers, but I don't think they will require you to do that)
int customPow(int base, int exponent) {
//Put your for in here, and may the pow be with you
}
You need to figure out the code yourself, but the general idea is as follows:
Create your own pow function which returns x*n.
int pow(int x, int n){
//use a for or while loop to calculate x (*x)n times.
//pay attention to the base cases (i.e., when n = 0, or 1 etc)
}
ans = 0;
for(i = 0 to N-1){
ans = ans + pow(x,i-1)*i;
}
I'm trying to write a C program which performs multiplication of two numbers without directly using the multiplication operator, and it should take into account numbers which are sufficiently large so that even the usual addition of these two numbers cannot be performed by direct addition.
I was motivated for this when I was trying to (and successfully did) write a C program which performs addition using character strings, I did the following:
#include<stdio.h>
#define N 100000
#include<string.h>
void pushelts(char X[], int n){
int i, j;
for (j = 0; j < n; j++){
for (i = strlen(X); i >= 0; i--){
X[i + 1] = X[i];
}
X[0] = '0';
}
}
int max(int a, int b){
if (a > b){ return a; }
return b;
}
void main(){
char E[N], F[N]; int C[N]; int i, j, a, b, c, d = 0, e;
printf("Enter the first number: ");
gets_s(E);
printf("\nEnter the second number: ");
gets_s(F);
a = strlen(E); b = strlen(F); c = max(a, b);
pushelts(E, c - a); pushelts(F, c - b);
for (i = c - 1; i >= 0; i--){
e = d + E[i] + F[i] - 2*'0';
C[i] = e % 10; d = e / 10;
}
printf("\nThe answer is: ");
for (i = 0; i < c; i++){
printf("%d", C[i]);
}
getchar();
}
It can add any two numbers with "N" digits. Now, how would I use this to perform multiplication of large numbers? First, I wrote a function which performs the multiplication of number, which is to be entered as a string of characters, by a digit n (i.e. 0 <= n <= 9). It's easy to see how such a function is written; I'll call it (*). Now the main purpose is to multiply two numbers (entered as a string of characters) with each other. We might look at the second number with k digits (assuming it's a1a2.....ak) as:
a1a2...ak = a1 x 10^(k - 1) + a2 x 10^(k - 2) + ... + ak-1 x 10 + ak
So the multiplication of the two numbers can be achieved using the solution designed for addition and the function (*).
If the first number is x1x2.....xn and the second one is y1y2....yk, then:
x1x2...xn x y1y2...yk = (x1x2...xn) x y1 x 10^(k-1) + .....
Now the function (*) can multiply (x1x2...xn) with y1 and the multiplication by 10^(k-1) is just adding k-1 zero's next to the number; finally we add all of these k terms with each other to obtain the result. But the difficulty lies in just knowing how many digits each number contains in order to perform the addition each time inside the loop designed for adding them together. I have thought about doing a null array and each time adding to it the obtained result from multiplication of (x1x2....xn) by yi x 10^(i-1), but like I've said I am incapable of precising the required bounds and I don't know how many zeros I should each time add in front of each obtained result in order to add it using the above algorithm to the null array. More difficulty arises when I'll have to do several conversions from char types into int types and conversely. Maybe I'm making this more complicated than it should; I don't know if there's an easier way to do this or if there are tools I'm unaware of. I'm a beginner at programming and I don't know further than the elementary tools.
Does anyone have a solution or an idea or an algorithm to present? Thanks.
There is an algorithm for this which I developed when doing Small Factorials problem on SPOJ.
This algorithm is based on the elementary school multiplication method. In school days we learn multiplication of two numbers by multiplying each digit of the first number with the last digit of the second number. Then multiplying each digit of the first number with second last digit of the second number and so on as follows:
1234
x 56
------------
7404
+6170- // - is denoting the left shift
------------
69104
What actually is happening:
num1 = 1234, num2 = 56, left_shift = 0;
char_array[] = all digits in num1
result_array[]
while(num2)
n = num2%10
num2 /= 10
carry = 0, i = left_shift, j = 0
while(char_array[j])
i. partial_result = char_array[j]*n + carry
ii. partial_result += result_array[i]
iii. result_array[i++] = partial_result%10
iv. carry = partial_result/10
left_shift++
Print the result_array in reverse order.
You should note that the above algorithm work if num1 and num2 do not exceed the range of its data type. If you want more generic program, then you have to read both numbers in char arrays. Logic will be the same. Declare num1 and num2 as char array. See the implementation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char num1[200], num2[200];
char result_arr[400] = {'\0'};
int left_shift = 0;
fgets(num1, 200, stdin);
fgets(num2, 200, stdin);
size_t n1 = strlen(num1);
size_t n2 = strlen(num2);
for(size_t i = n2-2; i >= 0; i--)
{
int carry = 0, k = left_shift;
for(size_t j = n1-2; j >= 0; j--)
{
int partial_result = (num1[j] - '0')*(num2[i] - '0') + carry;
if(result_arr[k])
partial_result += result_arr[k] - '0';
result_arr[k++] = partial_result%10 + '0';
carry = partial_result/10;
}
if(carry > 0)
result_arr[k] = carry +'0';
left_shift++;
}
//printf("%s\n", result_arr);
size_t len = strlen(result_arr);
for(size_t i = len-1; i >= 0; i-- )
printf("%c", result_arr[i]);
printf("\n");
}
This is not a standard algorithm but I hope this will help.
Bignum arithmetic is hard to implement efficiently. The algorithms are quite hard to understand (and efficient algorithms are better than the naive one you are trying to implement), and you could find several books on them.
I would suggest using an existing Bignum library like GMPLib or use some language providing bignums natively (e.g. Common Lisp with SBCL)
You could re-use your character-string-addition code as follows (using user300234's example of 384 x 56):
Set result="0" /* using your character-string representation */
repeat:
Set N = ones_digit_of_multiplier /* 6 in this case */
for (i = 0; i < N; ++i)
result += multiplicand /* using your addition algorithm */
Append "0" to multiplicand /* multiply it by 10 --> 3840 */
Chop off the bottom digit of multiplier /* divide it by 10 --> 5 */
Repeat if multiplier != 0.
Like the title say, how I calculate the sum of n number of the form: 1+(1/2!)+⋯(1/n!)? I already got the code for the harmonic series:
#include <stdio.h>
int main( void )
{
int v=0,i,ch;
double x=0.;
printf("Introduce un número paracalcular la suma: ");
while(scanf("%d",&v)==0 || v<=0)
{
printf("Favor de introducir numeros reales positivos: ");
while((ch=getchar())!='\n')
if(ch==EOF)
return 1;
}
for (i=v; i>=1; i--)
x+=1./i;
printf("EL valor de la serie es %f\n", x);
getch();
return 0;
}
The question here is.. I already got the sum as the fraction, but how make the variable "i" factorial?
Note: I´m programming in language C, with DEV -C++ 4.9.9.2
You got a slightly more accurate answer for the harmonic summing 1./i + 1./(i-1) ... 1./1. Suggest you stay with that order.
[edit] Rewrite: Thanks to #pablo197 for pointing out the error of my ways.
To calculate harmonic and 1+(1/2!)+…+(1/n!), continue summing the least significant terms together first as that helps to minimize precision loss. Starting with the least significant term 1/n as sum, sum of that and the n-1 term is : sum = (1 + sum)/(n-1) and so on. (See below)
double x = 0.0;
double one_over_factorial_series = 0.0;
for (i = v; i >= 1; i--) {
x += 1.0/i;
one_over_factorial_series = (one_over_factorial_series + 1)/i;
}
printf("harmonic:%le\n", x);
// 2.828968e+00
printf("one_over_factorial:%.10le\n", one_over_factorial_series);
// 1.7182815256e+00
Add 1.0 or 1/0! to one_over_factorial_series, the result about e = 2.7182818284...
[Edit] Detail showing how direct n! calculation is avoided.
1 + (1/2!) + … + (1/n!) =
1/n! + 1/((n-1)!) + 1/((n-2)!) + 1/((n-3)!) + ... + 1 =
(1/n + 1)/((n-1)!) + 1/((n-2)!) + 1/((n-3)!) + ... + 1 =
((1/n + 1)/(n-1) + 1)/((n-2)!) + 1/((n-3)!) + ... + 1 =
...
((((1/n + 1)/(n-1) + 1)/(n-2) + 1)/(n-3) + 1)/(n-4) + ... =
If you're just looking for computing the first n factorials, I would suggest just computing them recursively, e.g.
factorial[0] = 1;
for (i = 1; i < n; i++) factorial[i] = factorial[i-1] * i;
However, unless you store them as floating point numbers, the large factorials are going to overflow really quickly.
Calculating factorial in this case is bad thing to do because it can cause overflow for small values of N . Use following pseudo code to get it in O(N) without overflow.
double sum = 0.0;
double acc = 1;
double error = 0.0000001;
for(i=1;i<=n;i++) {
acc = acc/i;
if(acc<error)
break;
sum = sum + acc;
}
print(sum);
More acurrate way of doing it though i feel it is unnecessary in case of factorials : -
double sum = 0.0;
double acc = 1;
for(i=n;i>=1;i--) {
sum = (sum + 1)/i;
}
print(sum);
Note:- Because the above method is built in reverse it more accurate but unfortunately more time consuming because it is O(N) even for higher values whereas the gain in accuracy is negligible as factorial function grows very fast hence error keeps on decreasing quickly.
The number n! is equal to the product of n and the preceding factorial, that is, (n - 1)!.
If you calculate n! in an iteration, you are doing n products.
In the next step, say n+1, you repeat again these n products followed by the multiplication by n+1.
This means that you are repeating the same operations again and again.
It is a better strategy to hold the previous factorial that was calculated in the step n, and then, in the step n+1, just to multiply the n! by n+1. This reduces the number of products to 1 in each iteration.
Thus, you can calculate the series in the following way:
int max_n = 20; /* This value can come from another point of the program */
int n; /* Initial value of the index */
double factorial_n = 1; /* It has to be initialized to 1, since the factorial of 0 is 1 */
double sum = 0.0; /* It has to be initialized to 0, in order to calculate the series */
for (n = 0; n <= max_n; )
{
sum += 1.0/factorial_n;
n++;
factorial_n *= n;
}
printf("Series result: %.20f\n", sum);
There are some numerical issues with this approach, but this go beyond the scope of your question.
About overflow: It is necessary to be carefull about the overflow of factorials after several iterations. However, I will not write code to handle overflow.
EDIT
I think that you have not to follow the suggestions of those people that advice to use a factorial function. This approach is very unefficient, since a lot of products are done in every iteration.
IN comparisson with that approach, the mine is better.
However, if you have plans to calculate these series very often, then my approach is not efficient anymore. Then, the right technique is that pointed out in the Bli0042's answer, that is: to hold the factorials in an array, and then just use them every time you need, without need to calculate them again and again in the future.
The resulting program would be this:
#include <stdio.h>
#define MAX_N 100
double factorial[MAX_N+1];
void build_factorials(double *factorial, int max)
{
factorial[0] = 1.0;
for (int j = 0; j <= max; )
{
j++;
factorial[j] = factorial[j-1] * j;
}
}
double exp_series(int n)
{
int j;
double sum;
if (n > MAX_N) /* Error */
return 0.0;
sum = 0.0;
for (j = n; j >= 0; j--)
sum += 1.0/factorial[j];
return sum;
}
int main(void)
{
int n;
double sum;
build_factorials(factorial, MAX_N);
printf("Series (up to n == 11): %.20f\n", exp_series(11));
printf("Series (up to n == 17): %.20f\n", exp_series(17));
printf("Series (up to n == 9): %.20f\n", exp_series(9));
getchar();
}
The iteration is done in reverse order inside the function exp_series() in order to improve the numerical issues (that is, to amortiguate the loss of precision when summing small terms).
The last code has side effects, because an external array is invoked inside the function exp_series().
However, I think that handling this would become my explanation more obscure.
Just, take it in account.