Hello I wrote a loop to get the sum of the factorial of given value n divided by n with increasing exponent. To describe it better it looks like this:
But for some reason my loop is always returning the value 1 whenever I input a number.
Here's my loop:
int nVal, i, j, k, nProduct = 1, nSum = 0, nFactorial = 1;
float fResult;
for (i = 1; i <= nVal; i++)
{
for (j = 1; j <= nVal; j++)
{
nFactorial *= j;
nSum += nFactorial;
}
for (k = 1; k <= nVal; k++)
{
nProduct *= k;
}
fResult += (nSum * 1.0) / (nProduct * 1.0);
}
Any fixes I can try?
OP's code is incorrect in the numerator and denominator calculation. Also, the integer math readily overflows.
To better handle large n, form each term based on the prior term with floating point math.
double sum_fact_expo(int n) {
double sum = 0.0;
double ratio = 1.0;
for (int i = 1; i <= n; i++) {
ratio *= 1.0*i/n;
sum += ratio;
}
return sum;
}
How big will n get? This can dictate what the type for nProduct and nFactorial should be (e.g. int or long long or __int128 or double).
The nested/inner loops are wrong. You only want/need the for loop for i.
And you'll [possibly/probably] overflow/underflow if you wait to calculate the ratio. So, do this at each iteration.
Your factorial calculation line was okay. But, the nProduct calculation was incorrect. The multiplier has to be n [and not j].
You don't initialize fResult, so it starts with a random value (i.e. undefined behavior). This would be flagged if you compiled with -Wall [and -O2] to enable warnings.
Remember that:
k! = (k - 1)! * k
And, that:
n**k = n**(k - 1) * n
So, we can build up nFactorial subterms and nProduct subterms iteratively, in a single loop.
Here's what I think your code should be like:
// pick _one_ of these:
#if 0
typedef int acc_t;
#endif
#if 0
typedef long long acc_t;
#endif
#if 0
typedef __int128 acc_t;
#endif
#if 1
typedef double acc_t;
#endif
double
calc1(int nVal)
{
int i;
acc_t nProduct = 1;
acc_t nFactorial = 1;
double ratio;
double fResult = 0;
for (i = 1; i <= nVal; ++i) {
nFactorial *= i;
nProduct *= nVal;
ratio = (double) nFactorial / (double) nProduct;
fResult += ratio;
}
return fResult;
}
#include <stdio.h>
int main(void) {
int nVal, i, j, k, nProduct = 1, nFactorial = 1;
float fResult = 0;
scanf("%d", &nVal);
for (i = 1; i <= nVal; i++)
{
for (j = 1; j <= i; j++)
{
//calculate 1! 2! 3! ... n!
//actually calculate i!
nFactorial *= j;
}
for (k = 1; k <= i; k++)
{
//calculate n^1 n^2 n^3 ... n^n
//actually calculate n^i
nProduct *= nVal;
}
fResult += (nFactorial * 1.0) / (nProduct * 1.0);
nProduct = 1;
nFactorial = 1;
}
printf("%f\n", fResult);
return 0;
}
Related
I am approximating Runge’s function using Lagrange’s interpolation formula for 50 interpolation points. I have written the following program to do this, but I am getting the wrong value for x= -0.992008. That wrong value is 4817543.091313, but it should be 5197172.55933613. I have got this value from the following link: Link The code used are as follows:
#include <stdio.h>
#include <math.h>
double
runge(double x)
{
return (1 / (1 + (25 * x * x)));
}
double
ab(double x)
{
if (x < 0)
return -1 * x;
return x;
}
double
lag_func(double x, double *y_i, double *x_i, int n)
{
double ex = 0.0;
for (int i = 0; i <= n; i++) {
double numer = 1.0,
denom = 1.0,
prod = 1.0;
for (int j = 0; j <= n; j++) {
if (i != j) {
numer = (x - x_i[j]);
denom = (x_i[i] - x_i[j]);
prod *= numer / denom;
}
}
ex += (prod) * y_i[i];
}
return ex;
}
int
main()
{
int n;
scanf("%d", &n);
double y_i[n + 1],
x_i[n + 1];
for (int i = 0; i < n + 1; i++) {
x_i[i] = ((2 * (double) i) / (double) n) - 1;
y_i[i] = runge(x_i[i]);
}
printf("%lf\n", lag_func(-0.992008, y_i, x_i, n));
return 0;
}
The web site is rounding its Runge coefficients to six digits. Given the magnitudes of the terms involved, up to 3.9978•1011, this introduces multiple errors up to around 2•105.
This can be seen by inserting y_i[i] = round(y_i[i] * 1e6) / 1e6; after y_i[i] = runge(x_i[i]);. Then the output of the program is 5197172.558199, matching the web site’s inaccurate result.
The web site is wrong; the result of the code in the question is better.
Edit: thanks, fixed the i and j and now it works when my antivirus is off, but McAfee still blocks the project when activated...
I'm trying to run this code and McAfee keeps interfering. after disabling it for a few minutes, the code was compiled (with no errors) but the output is just 'inf' what does that mean?
I'm not sure that the code is correct but I still excepted it run properly, trying to debug, it seems that it's not actually running...
probably some dumb mistake I haven't noticed.
will appreciate any help.
double factorial(double num)
{
double j, factor = 1;
for (j = 1; j < num; j++)
{
factor *= j;
}
return factor;
}
double sum_of_sequence(double x, int n)
{
double i, f = 0;
double sum = 0;
int power = 2 * n + 1;
for (i = 1; i < power; i += 2)
{
double factor = factorial(f);
double numerator = pow(x, i);
sum += numerator / (i * factor);
f++;
}
return sum;
}
void main()
{
double x = 1;
int n = 2;
double res = sum_of_sequence(x, n);
printf("%lf", res);
}
Write a program in C to find the sum of the series [ 1-X^2/2!+X^4/4!- .........]
Test Data:
Input the Value of x :2
Input the number of terms : 5
Expected Output:
the sum = -0.415873
Number of terms = 5
Here is the code I wrote, no compilation error, I just wasnt getting the answer right:
#include <stdio.h>
#include <math.h>
int main()
{
float sum=0;
float ans;
int c, y, fac=1;
int a,i, x=2;
float z;
for (i = 1; i<=2; i++)
{
a= 2*i;
y = pow(2,a);
for (c = 1; c<=a; c++)
{
fac= fac*c;
}
z = (float) y/fac;
if (i%2 == 0) {
sum = sum + z;
}
else{
sum = sum - z;
}
}
ans = 1 + sum;
printf("The answer is %f" , ans);
return 0;
}
You didn't used number of terms.
You didn't set fac to 1 to the end of the for.
y is equal to pow(x,a) not pow(2,a).
Int can store numbers between -2,147,483,648 and 2,147,483,647, so I recommend to use long long (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807). And also, double instead of float. You can take a look here for more details: https://learn.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=msvc-160.
Here is the code:
#include <stdio.h>
#include <math.h>
int main()
{
double sum=0;
double ans;
long long c, y, fac=1;
long long a,i, x=2, numberOfTerms = 5;
float z;
for (i = 1; i<= numberOfTerms; i++)
{
a= 2*i;
y = pow(x,a);
for (c = 1; c<=a; c++)
{
fac= fac*c;
}
z = (double) y/fac;
if (i%2 == 0) {
sum = sum + z;
}
else{
sum = sum - z;
}
fac = 1;
}
ans = 1 + sum;
printf("The answer is %f" , ans);
return 0;
}
Try to use functions.
If you do not have to, do not use float. Use double for floating point calculations.
Your code does not reflect the formula at all.
double fact(unsigned n)
{
double result = 1.0;
for(unsigned x = 1; x <= n; x++)
result *= x;
return result;
}
double series(double x, unsigned nterms)
{
double result = 1;
for(unsigned term = 1; term <= nterms; term++)
{
result += (1.0 - ((term & 1) << 1)) * pow(x, (double)term * 2.0) / fact(term * 2);
}
return result;
}
int main(void)
{
for(unsigned nterms = 2; nterms < 20; nterms++)
{
printf("nterms = %2u series(4) = %.32f\n", nterms, series(4.0, nterms));
}
}
https://godbolt.org/z/8c3xM4
I need to write a function to get a curve fit of a dataset. The code below is what I have. It attempts to use gradient descent to find polynomial coefficients which best fit the data.
//solves for y using the form y = a + bx + cx^2 ...
double calc_polynomial(int degree, double x, double* coeffs) {
double y = 0;
for (int i = 0; i <= degree; i++)
y += coeffs[i] * pow(x, i);
return y;
}
//find polynomial fit
//returns an array of coefficients degree + 1 long
double* poly_fit(double* x, double* y, int count, int degree, double learningRate, int iterations) {
double* coeffs = malloc(sizeof(double) * (degree + 1));
double* sums = malloc(sizeof(double) * (degree + 1));
for (int i = 0; i <= degree; i++)
coeffs[i] = 0;
for (int i = 0; i < iterations; i++) {
//reset sums each iteration
for (int j = 0; j <= degree; j++)
sums[j] = 0;
//update weights
for (int j = 0; j < count; j++) {
double error = calc_polynomial(degree, x[j], coeffs) - y[j];
//update sums
for (int k = 0; k <= degree; k++)
sums[k] += error * pow(x[j], k);
}
//subtract sums
for (int j = 0; j <= degree; j++)
coeffs[j] -= sums[j] * learningRate;
}
free(sums);
return coeffs;
}
And my testing code:
double x[] = { 0, 1, 2, 3, 4 };
double y[] = { 5, 3, 2, 3, 5 };
int size = sizeof(x) / sizeof(*x);
int degree = 1;
double* coeffs = poly_fit(x, y, size, degree, 0.01, 1000);
for (int i = 0; i <= degree; i++)
printf("%lf\n", coeffs[i]);
The code above works when degree = 1, but anything higher causes the coefficients to come back as nan.
I've also tried replacing
coeffs[j] -= sums[j] * learningRate;
with
coeffs[j] -= (1/count) * sums[j] * learningRate;
but then I get back 0s instead of nan.
Anyone know what I'm doing wrong?
I tried degree = 2, iteration = 10 and got results other than nan (values around a few thousands) Adding one to iteration seems making magnitude of the results larger by about 3 times after that.
From this observation, I guessed that the results are being multiplied by count.
In the expression
coeffs[j] -= (1/count) * sums[j] * learningRate;
Both of 1 and count are integers, so integer division is done in 1/count and it will become zero if count is larger than 1.
Instead of that, you can divide the result of multiplication by count.
coeffs[j] -= sums[j] * learningRate / count;
Another way is using 1.0 (double value) instead of 1.
coeffs[j] -= (1.0/count) * sums[j] * learningRate;
Aside:
A candidate NAN source is adding opposite signed values where one is an infinity. Given OP is using pow(x, k), which grows rapidly, using other techniques help.
Consider a chained multiplication rather than pow(). The result is usually more numerically stable. calc_polynomial() for example:
double calc_polynomial(int degree, double x, double* coeffs) {
double y = 0;
// for (int i = 0; i <= degree; i++)
for (int i = degree; i >= 0; i--)
//y += coeffs[i] * pow(x, i);
y = y*x + coeffs[i];
}
return y;
}
Similar code could be used for the main() body.
double taylor_log(double x, unsigned int n){
double tmp;
double sum = 0;
if(x < 1){
int j = 2;
x = 1 - x;
tmp = x;
sum = -x;
for(unsigned int i = 1; i < n; i++){
sum -= ((tmp *= x) / j);
j++;
}
return sum;
}
else if (x >= 1){
tmp = ((x-1)/x);
for(unsigned int i = 1; i <= n; i++){
sum += (tmp/i);
tmp *= ((x-1)/x);
}
return sum;
this is my fuction for log with taylor series wich work correctly.
Im using this formula to get exponetional fuction of number.formula for mypow()
and this is my code for pow
double taylor_pow(double x, double y, unsigned int n){
double sum = 1.0;
int fac = 1;
double exp = y;
double lna = taylor_log( x, n);
for(unsigned int i = 1; i <= n; i++){
fac *= i;
sum += (exp * lna / fac );
exp *= y;
lna *= taylor_log( x, n);
}
return sum;
}
Now my problem is that if i put for example 30 iterations for my function the number is higher than pow(). For example pow(2,3) = 8 and my result with 20 iterations is 8.0007... and its growing. Thans for all responses.
int fac is overflowing. Changed it to long double, and it works much better.
A 32 bit signed int will only hold values up to 12!, while an 80 or 128 bit long double can hold something like 2000!.