Here is my code, when using print statements it appeared to be an infinite loop:
some potential issues i can troubleshoot are integer division, and perhaps figuring out if the algorithm terminates, and if it always has the correct output, perhaps there is some idiosyncrasy of the C language that I do not understand causing this issue?
From my understanding as the sum tends to negative infinity it will cause the break statement to be triggered ending the algorithm once it reaches an approximation of epsilon precision.
#include <stdio.h>
int main()
{
double pi, sum, epsilon;
long long i=1;
long long max = 2147483647;
printf("Pleas enter the desired accuracy epsilon : ");
scanf("%f", &epsilon);
while (i<max){
if (i%2 == 0){
sum = -4.0/(2.0*i-1);
}else if (i%2 ==1){
sum = (4.0/(2.0*i-1));
}
if (sum < epsilon){
break;
}
pi += sum;
}
printf("The value of pi approximated to epsion : %f is %f\n", epsilon, pi);
return 0;
}
You are not increment the value of i in your while loop. As a result its value always remains 1.
Increment i after your processing is done before the closing } of the while loop.
Initialize the values of pi, sum, epsilon so that you do not run into undefined behavior when you try to read their values for the first time.
Also, with proper options enabled (-Wall with GCC) the compiler will warn you, that you are trying to read a float into a double.
warning: format '%f' expects argument of type 'float *', but argument 2 has type 'double *' [-Wformat=]
scanf("%f", &epsilon);
~^ ~~~~~~~~
So you have to use the correct conversion specifier: %lf instead of %f in your scanf statement.
If you are not very particular about the number 2147483647 and just want a large value, you can also use ULLONG_MAX (from limits.h) to initialize max instead of hard-coding the value.
You need to increment i value in while loop.
Your looping condition while(i < max) is always satisfied (infinite loop). So the value of i or max should be changed inside the loop to ever end the loop.
Your code has undefined behavior:
scanf("%f", &epsilon);
scanf %f takes a float *, not double *. The correct format for double * is %lf.
Your loop condition while (i<max) is equivalent to while (1) as neither i nor max change their value inside the loop.
This also means sum is always 4:
sum = (4.0/(2.0*i-1));
// 4 / (2 * 1 - 1) = 4 / (2 - 1) = 4 / 1 = 4
pi += sum;
also has undefined behavior: pi is uninitialized.
Related
Going to post the whole code so if there is something else you can help me.
The idea of the program is to know if the inserted number is multiple of 5, power of 10 or a perfect square (I'm not English, a bit unsure if this word is the one I'm looking for).
int main (void){
int i,b=0,rqi;
printf("Insert a number from 1 to 10000: ");
scanf("%d",i);
double rq=sqrt(i),p=log(i);
if(i%5==0){
printf("It's a multiple of 5\n");
b=1;
}
if(p%1==0){
int pi=p;
printf("It's a power of 10 (%d=10^%d)\n",i,pi);
b=1;
}
if(rq%1.0==0){
rqi=rq;
printf("It's a perfect square (%d = %d*%d)\n",i,rqi,rqi);
}
if(b==0){
printf("It doesn't satisfies any condition.\n");
}
return 0;
}
The errors I'm getting are
warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int’ [-Wformat=]
scanf("%d",i);
^
error: invalid operands to binary % (have ‘double’ and ‘int’)
if(p%1==0)
^
invalid operands to binary % (have ‘double’ and ‘double’)
if(rq%1.0==0)
Also, I learned a bit of java and not C, is there a way to make a boolean or making an int 0 or 1 is the way to go?
scanf("%d",i);
Pass address of int .Write like this -
scanf("%d",&i);
% operator cannot be used on double or float . Remainder is just concerned for integer values .
Use fmod function for the above task to get remainder.
Like this you can do this and incorporate it in your if condition-
fmod(p,1.0) // gives remainder of p divided by 1.0
But probably don't compare double values using ==.
Seems like you should check fmod function.
Also, if you want to check whether a double is of integer's range or not, you can check if it's value is equal to it's floor's value or not, using floor fucntion.
if(double_num == floor(double_num)) return 1;
else return 0;
You are basically dealing with integers here. Floating-point arithmetic has its inaccuracies; it might be better to do the comparison with integers instead.
int is_square(unsigned int x)
{
int r = sqrt(x) + 0.5;
return (r*r == x);
}
Here, a (crudely) rounded integer root is calculated first. Then you check back whether squaring it gives you back your original number.
int is_power10(unsigned int x)
{
while (x && x % 10 == 0) x /= 10;
return (x == 1);
}
Strip off trailing zeros. If all that's left is a 1, you've got a power of 10.
I'm VERY new to programming, and I'm using a book to help me write some code that will solve ln(1+x) after the user inputs "x". My syntax is exactly the way the book has it in its example but I keep getting an error: expected expression before 'long' on line 28. Line 28 is the line that reads long double y = LOG(1+(x));.
#include <stdio.h>
#include <math.h>
#define LOG(X) _Generic((X),\
long double: log(1+(x))\
)
int main()
{
double x;
printf("Please enter a number from -1 to +1: ");
scanf("%f", &x);
long double y = LOG(1+(x));
printf("From C math library: ln(1+x) = %f\n", y);
}
Firstly, your generic macro is written for long double type. You supplied a double argument x. long double and double are two different types. You did not define a generic branch for double, which means that your macro will not compile for a double argument. Either change the type of x to long double or make your generic macro support double arguments.
Also, this is a very strange way to write a LOG macro. Why are you explicitly using 1 + (x) as log argument inside the macro? What if tomorrow you'll want to calculate LOG(2 + y)? Your macro will still insist on calculating log(1 + (x)) instead, which does not make any sense at all. A more sensible thing to do would be to just pass X to log
#define LOG(X) _Generic((X),\
long double: log(X)\
)
Secondly, in order to scanf a double value you need %lf format specifier. %f is for float. To printf a long double value you need %Lf format.
If you are new to programming, and trying to make an example work, I would not use macros at this stage but focus on the function and the data type. Start with a double which is the typical working type of the library interfaced by math.h. My example shows how to calculate the natural ln with the log() function.
As others have commented, scanf() needs a format specifier of %lf for a double, however printf() only needs the format specifier of %f for a double. Note that I have tested the return value from scanf() function as well as the number you input, to check that the input was well behaved.
Lastly, you invite numbers in the range -1 <= x <= 1 yet ln(0) is undefined, hence I have restricted the input range to exclude -1.
#include <stdio.h>
#include <math.h>
int main(void)
{
double x = 0, y;
printf("Please enter a number from -1 to +1: ");
if (1 != scanf("%lf", &x) || x <= -1 || x > 1) {
printf("I need -1 < number <= +1\n");
return 1;
}
y = log(x + 1);
printf("From C math library: ln(1+x) = %f\n", y);
return 0;
}
Here are some sample outputs:
Please enter a number from -1 to +1: -1
I need -1 < number <= +1
Please enter a number from -1 to +1: 0
From C math library: ln(1+x) = 0.000000
Please enter a number from -1 to +1: 1
From C math library: ln(1+x) = 0.693147
The program compiles but when running it I am not getting the correct values back from my inputs. I have looked for a way to make the sine formula and have found this one but I don't believe it was right.
Is my formula correct? I think just running the sin function in C is giving me the wrong value as well.
Update: I'm still getting the wrong values with these changes if I input 1.5 and 4. I'm getting 0.000 and a random integer
/*
* Function mySin is using a sin formula to get the sin of x
* the function then returns the sin value computed
* Parameters -for function mySin are "x" is the value for sin
* -"n"is the number of series to run
*
*The program also uses the sin(x) function to get the real sin
*
*/
#include <stdio.h>
#include <math.h>
int mySin(double x, int n){
int i=0;
double sinx=0;
for(i=1; i<=n; i+=2){
sinx=(pow(x,i)+sinx); //
}
return sinx;
}
int main(double sinx){
double realSin=0;
double x=0;
int n=0;
printf("Please input x and n:");
scanf("%lf",&x);
scanf("%d",&n);
mySin(x,n);
realSin=sin(x);
printf("mySin= %f\n sin=%d\n",sinx,realSin);
}
Your mySin function is wrong in at least 5 separate ways. Using ** to represent exponentiation (to avoid confusion with xor), the correct formula is
sin(x) = x - x**3/3! + x**5/5! - x**7/7! + x**9/9! ...
Your implementation fails because
It discards the previous terms on every iteration of the loop.
It doesn't alternate signs.
It includes even-exponent terms.
It doesn't compute a factorial in the divisor.
The return type is int, discarding the fractional component of the computed result.
Furthermore, main is wrong in several more ways. The return value of mySin is completely ignored. Instead, sinx is the first argument to main, which is the number of command-line arguments the program received (including the name it was run as). Also, %d is used for all numbers in format strings, regardless of type, when it's only meant for int.
To fix mySin, have i only go over odd values, and have every iteration of the loop compute x**i/i! and add it into the current value of sinx.
To fix main, declare a local sinx variable in main and assign sinx = mySin(x, n) instead of declaring sinx as an argument. Also, use %lf for reading doubles with scanf and %f for writing doubles with printf.
x is double so you have to use the %lf in scanf and %f in the printf
double x;
scanf("%lf", &x);
printf ("%f", x);
One more incorrect point in your code is that you're calculating power by **
There's no power operator in C. The compiler is treating x**i as x * (*i). But since i is not a pointer, it returns the error you saw. You must use pow() instead
mySin should return double. You are returning int.
sin values can be calculated with the Fourier series.
I have a program here that is supposed to sum up the series
1+1/2+1/3+1/4... etc
The only user entry is to enter how many times you want this sum to run for.
However, I keep getting the sum one.
#include <stdio.h>
int main(void)
{
int b,x; /* b is number of times program runs and x is the count*/
float sum;
printf("Enter the number of times you want series to run.\n");
scanf("%d", &b);
printf("x sum\n");
for(x=1,sum=0;x<b+1;x++)
{
printf("%d %9.3f\n",x, (sum +=(float)(1/x)));
}
return 0;
}
I don't quite get why it isn't working. As you can see, I did tell it to print x and when it did, x was incrementing correctly.The sum just kept adding up to one.
You have misplaced parentheses so you're doing integer division for 1/x and getting 0 for any value of x > 1.
I suggest you change:
printf("%d %9.3f\n",x, (sum +=(float)(1/x)));
to:
printf("%d %9.3f\n",x, (sum += 1.0f/x));
Two problems: one dull, one interesting.
1) 1 / x will be imprecise since 1 and x are both integral types and so the computation will be done in integer arithmetic. All the cast does is convert the resultant integral type to floating point. To resolve this, write 1.0 / x. Then 'x' is promoted to floating point prior to the division.
2) You should reverse the order of the for loop:
sum = 0.0;
for(x = b; x >= 1; --x)
(I've also moved the initialisation or sum from the for loop as sum = 0 is an expression of type float but x = b is an expression of type int so you ought not use the comma operator as they have different data types.)
The reason is subtle: you should only add floating points of similar magnitude. Doing the loop my way means the smaller values are added first.
The effect will be noticeable for high values of b; try it. Your original way will always understate the sum.
The problem is integer division when you do 1/x, which always result in 0 as long as x is greater than 1. Even it you later convert this to a float, the "damage" is already done. An easy fix would be to change the division to 1.0f/x.
Since you have declared x as an int, (1/x) returns 1 when x is 1 and 0 for x>1. So, sum remains 1. So you get the same result.
So, change (1/x) to 1.0f/x, so that the result is returned as a float
Here you are computing 1/x in which the fractional value is truncated. Converting it into float after the original value has been truncated doesn't make sense.
So change this to:-
printf("%d %9.3f\n",x, (sum +=(float)(1/x)));
to
printf("%d %9.3f\n",x, (sum += 1.0f/x));
The expression (1/x) will always be integer division. For the first run this will be 1/1 giving you 1. However, next time round it will be 1/2 which is 0. Basically for 1/x where x>1 the answer will be zero.
To get around this write the expression as 1.0/x which will cause x to be promoted to a double, giving you double division.
Could someone tell me why the following code is outputting 0 at the marked line?
It seems as if everything is correct but then when I try to get the result near the end it's giving me 0 each time.
#include <stdio.h>
int main() {
// Gather time-lapse variables
int frameRate, totalLengthSecs;
printf("How many frames per second: ");
scanf("%i", &frameRate);
printf("--> %i frames confirmed.", frameRate);
printf("\nDesired length of time-lapse [secs]: ");
scanf("%i", &totalLengthSecs);
printf("--> %i seconds confirmed.", totalLengthSecs);
int totalFrames = frameRate * totalLengthSecs;
printf("\nYou need %i frames.", totalFrames);
// Time-lapse interval calculation
int timeLapseInterval = totalLengthSecs / totalFrames;
printf("\n\n%i", timeLapseInterval); // <-- this prints 0
return 0;
}
In short: Integer division truncates
You need the following:
double timeLapseInterval = (double) totalLengthSecs / (double)totalFrames;
printf("\ntimeLapseInterval : %f \n", timeLapseInterval);
You are performing integer math.
Math between two integers will produce an integer. And the result will be rounded towards zero.
This line:
totalLengthSecs / totalFrames;
Is likely producing a result that's between 0 and 1. And getting rounded to 0
You are printing integers and therefore it will round down the value.
timeLapseInterval / totalFrames will be (1 / frameRate) which will be < 1 unless frameRate is 1 (or 0 in which case you have an error dividing by 0)
When you divide 2 numbers in C and the denominator is integer, the compiler intends it as an integer division. Therefore, if you divide 1 divided 2, it returns zero and not 0.5
Moreover, your output variable is an integer too, hence, if you expect decimal outputs, you won't get it.
You can fix it by doing:
float timeLapseInterval = totalLengthSecs / (float)totalFrames;
printf("\n\n%f", timeLapseInterval);
I hope this helps