Example 1-7 from The C Programming Language(version 2) - c

I am having trouble understanding the example 1.7 given in The C Programming Language. The main purpose of this example is to illustrate the use of functions in C. The book describes the following program as such, "Since C has no exponentiation operator like ** of Fortran, let us illustrate the mechanics of function definition by writing a function power(m,n) to raise an integer m to a positive power n. That is, the value of power(2,5) is 32. This function is not a practical exponentiation routine since it handles only positive powers of small integers, but it's good enough for illustration."
This is the block of C code that follows:
#include <stdio.h>
int power(int m, int n); /*function prototype */
int main() {
/* test power function */
int i;
for(i = 0; i < 10;++i)
printf("%d %d %d\n",i,power(2,i),power(-3,i));
return 0;
}
/* power: raise base to the nth power;n >=0 */
int power(int base,int n) {
int i , p;
p = 1;
for(i = 1;i <= n;++i)
p = p * base;
return p;
}
I understand everything up to the power function's code block. What is confusing me is that for loop. I am still learning C(obviously, i'm in the first chapter) but I come from JavaScript. So when I see this for loop I expect the i to need to be 'bound' to something for it to be of us in iteration(similar to the first for loop in the example). But the power function returns p after p = p * base;. It's not returning anything to do with i. So to me, I think, what is the purpose of this for loop? I notice that if I comment out the for loop and remove the integer i then the numbers printed out do not increment except for the numbers within the previous for loop. To me, I expect the int n would need to increment. Not the i.
It appears to me that within the for loop that n is only being used as comparison to i. Is the purpose of the for loop in the power function only to execute p = p * base if i <= n is true? That can't be true because if that was then it would better be server with just an if statement and wouldn't need a ++i to increment.
What am I missing here?

The for-loop in the power function repeatedly multiplies (and updates) p by base. It does this n times -- i is the counter. If an if-statement were used, then you'd only get up to one multiplication.

Related

Why does my approximation of Exponential using Taylor Series expansion return "inf"?

This is my homework:
I haven't tried to write the part of Natural Logarithm because I can't solve the part of Exponential.
This is the the approximations of Exponential in C using Taylor Series expansion I wrote.
However, it returns inf. What did I do wrong?
#include <stdio.h>
// Returns approximate value of e^x
// using sum of first n terms of Taylor Series
float exponential(int n, float x)
{
float sum = 1.0f; // initialize sum of series
for (int a = n; a >= 0; ++a ) {
while (x * sum / a < 0.00001) {
break;
}
sum = 1 + x * sum / a;
return sum;
}
}
int main()
{
int n = 0;
float x = 1.0f;
printf("e^x = %.5f", exponential(n, x));
return 0;
}
With How do I ask and answer homework questions? in mind, I will give you a few things to have a careful look at.
From comment by Spektre:
from a quick look you are dividing by zero in while (x * sum / a < 0.00001) during first iteration of for loop as a=n and you called the function with n=0 ... also your code does not match the expansion for e^x at all
Have a look at the for loop:
for (int a = n; a >= 0; ++a )
What is the first value of a? The second? The third?
Keep in mind that the values are determined by ++a.
When will that loop end? It is determined by a >= 0. When is that false?
What is this loop doing?
while (x * sum / a < 0.00001) {
break;
}
I suspect that you programmed "English to C", as "do the outer loop while ...", which is practically from the assignment.
But the loop does something else. Apart from risking the division by 0 mentioned above, if the condition is true it will stay true and cause an endless loop, which then however is immediatly canceled in the first iteration.
The head of your function float exponential(int n, float x) expects n as a parameter. In main you init it with 0. I suspect you are unclear about where that value n is supposed to come from. In fact it is unknown. It is more a result of the calculation than an input.
You are supposed to add up until something happens.
You do not actually ever need the value of n. This means that your for loop is meaningless. The inner loop (though currently pointless) is much closer to your goal.
I will leave it at this for now. Try to use this input.
Feel free to edit the code in your question with improvements.
(Normally that is not appreciated, but in case of homework dialog questions I am fine with it.)
Your current implementation attempt is quite a bit off. Therefore I will describe how you should approach calculating such a series as given in your quesiton.
Let's look at your first formula:
You need to sum up terms e(n) = x^n / n!
To check with your series: 1 == x^0 / 0! - x == x^1 / 1! - ...
To calculate these terms, you need a simple rule how to get from e(n) to e(n+1). Looking at the formula above we see that you can use this rule:
e(n+1) = e(n) * x / (n+1)
Then you need to create a loop around that and sum up all the bits & pieces.
You are clearly not supposed to calculate x^n/n! from scratch in each iteration.
Your condition to stop the loop is when you reach the limit of 1e-5. The limit is for the new e(n+1), not for the sum.
For the other formulas you can use the same approach to find a rule how to calculate the single terms.
You might need to multiply the value by -1 in each step or do something like *x*n/(n+1) instead of *x/(n+1) etc.
Maybe you need to add some check if the formula is supposed to converge. Then maybe print some error message. This part is not clear in your question.
As this is homework, I only point into the direction and leave the implementation work to you.
If you have problems with implementation, I suggest to create a new question.
#include <stdio.h>
int main() {
float power;
printf("Enter the power of e\n");
scanf("%f", &power);
float ans = 1;
float temp = 1;
int i = 1;
while ((temp * power) / i >= 0.00001) {
temp = (temp * power) / i;
ans = ans + temp;
i++;
}
printf("%.5f", ans);
return 0;
}
I think I solved the problem
But the part about Natural Log is not solved, I will try.

The difference between n++ and ++n at the end of a while loop? (ANSI C)

this is probably a dumb question but I just can't figure it out. It has to do with the differences between n++ and ++n (which I thought I understood but apparently not).
#include <stdio.h>
#include <math.h>
long algorithmA(int n);
long algorithmB(int n);
int main(){
long A, B;
A = B = 0;
int n = 1;
while(A >= B){
A = algorithmA(n);
B = algorithmB(n);
n++;
}
printf("At n = %d, Algorithm A performs in %ld seconds & "
"Algorithm B performs in %ld seconds.", n, A, B);
}
long algorithmA(int n){
return pow(n,4) * 86400 * 4;
}
long algorithmB(int n){
return pow(3,n);
}
Here you can probably tell I'm trying to see at what point Algorithm A outperforms Algorithm B. The functions and units of time were given to me in a homework problem.
Anyways, I always thought that the order of "++" would not matter at the end of a while loop. But if I put ++n instead of n++, I get the wrong answer. Can somebody explain why?
Edit: Well it WAS showing 24 with ++n and 25 with n++, but it must have been for another reason. Because I just checked now and there is no difference. Thanks for your patience and time guys, I just wish I knew what I did!
If you increment without assignment, no difference. However, in the following circumstances, there is:
int n = 1;
int x = n++; // x will be 1 and n will be 2
In this example, the statement gets executed prior to the increment.
int n = 1;
int x = ++n; // both x and n will be 2
However, in this example, increment occurs prior to the execution of the statement.
Operator precedence can help you out.
The only difference between n++ and ++n is that n++ yields the original value of n, and ++n yields the value of n after it's been incremented. Both have the side effect of modifying the value of n by incrementing it.
If the result is discarded, as it is in your code, there is no effective difference.
If your program is behaving differently depending on whether you write
n++;
or
++n;
it must be for some other reason.
In fact, when I compile and execute your program on my system, I get exactly the same output in both cases. Adding newlines to the output format, I get:
At n = 25, Algorithm A performs in 114661785600 seconds &
Algorithm B performs in 282429536481 seconds.
You haven't told us what output you're getting. Please update your question to show the output in both cases.
The prefix versions (++n) alter the variable and then pass along its value.
The postfix version (n++) pass along the current value and then alter the variable.

please explain shellsort code in C

This code is written in ANSI C by Ritchie..... I have used a comment in this code that my doubt. Also i have learnt shell sort from youtube and have understood how it actually works but this code is very confusing specially these loop....why have they used gap= n/2....what is gap? and what are these loop doing here.....Plz :(
void shellsort(int v[], int n)
{
int gap, i, j, temp;
for(gap= n/2; gap >0; gap /=2) // What is this gap /=2
for(i=gap; i<n; i++)
for(j= i-gap; j>= 0 && v[j]>v[j+gap]; j -=gap){
temp= v[j];
v[j]=v[j+gap];
v[j+gap]=temp;
}
}
what edition of the book are you reading from? i think there are a number of programming errors in the example code all the way untill 3rd edition.
gap refers to the int you declared above the for loop. like gap, i, j & temp are also integers. this means they hold a integer numeric value (e.g, 1,2, 12, 586 etc).
a /= b is a division assignment so its literal meaning is a = a / b.
you might also be wondering what v & n are?
int v[] refers to an int array, so any value used inside the [ ] is the index of that array, e.g v[0], v[1], v[2], v[n]...
Since v & n are declared as parameters of the shellsort function, it means that when you call the function, it will need to be passed an int array value, as well as an int value. without these values the function cannot operate properly
if you have the C book, everything you need to know about C will be in that book :)

How to Approximate e in an Infinite Series in C

So I am trying to do this problem:
However, I'm not entirely sure where to start or what exactly I am looking for.
In addition, I was told I should expect to give the program inputs such as: zero (0), very small (0.00001), and not so small (0.1).
I was given this: http://en.wikipedia.org/wiki/E_%28mathematical_constant%29 as a reference, but that formula doesn't look exactly like the one in the problem.
And finally, I was told that the input to the program is a small number Epsilon. You may assume 0.00001f, for example.
You keep adding the infinite series until the current term's value is below the Epsilon.
But all in all, I have no clue what that means. I somewhat understand the equation on the wiki. However, I'm not sure where to start with the problem given. Looking at it, does anyone know what kind of formula I should be looking to use in C and what "E" is and where it comes into play here (i.e. within the formula, I understand it's suppose to be the user input).
Code So Far
#include <stdio.h>
#include <math.h>
//Program that takes in multiple dates and determines the earliest one
int main(void)
{
float e = 0;
float s = 0;
float ct = 1;
float ot= 1;
int n = 0;
float i = 0;
float den = 0;
int count = 0;
printf("Enter a value for E: ");
scanf("%f", &e);
printf("The value of e is: %f", e);
for(n = 0; ct > e; n++)
{
count++;
printf("The value of the current term is: %f", ct);
printf("In here %d\n", count);
den = 0;
for(i = n; i > 0; i--)
{
den *= i;
}
//If the old term is one (meaning the very first term), then just set that to the current term
if (ot= 1)
{
ct = ot - (1.0/den);
}
//If n is even, add the term as per the rules of the formula
else if (n%2 == 0)
{
ct = ot + (1.0/den);
ot = ct;
}
//Else if n is odd, subtract the term as per the rules of the formula
else
{
ct = ot - (1.0/den);
ot = ct;
}
//If the current term becomes less than epsilon (the user input), printout the value and break from the loop
if (ct < epsilon)
{
printf("%f is less than %f",ct ,e);
break;
}
}
return 0;
}
Current Output
Enter a value for E: .00001
The value of e is: 0.000010
The value of the current term is: 1.000000
In here 1
-1.#INF00 is less than 0.000010
So based on everyone's comments, and using the 4th "Derangements" equation from wikipedia like I was told, this is the code I've come up with. The logic in my head seems to be in line with what everyone has been saying. But the output is not at all what I am trying to achieve. Does anyone have any idea from looking at this code what I might be doing wrong?
Σ represents a sum, so your equation means to compute the sum of the terms starting at n=0 and going towards infinity:
The notation n! means "factorial" which is a product of the numbers one through n:
Each iteration computed more accurately represents the actual value. ε is an error term meaning that the iteration is changing by less than the ε amount.
To start computing an interation you need some starting conditions:
unsigned int n = 0; // Iteration. Start with n=0;
double fact = 1; // 0! = 1. Keep running product of iteration numbers for factorial.
double sum = 0; // Starting summation. Keep a running sum of terms.
double last; // Sum of previous iteration for computing e
double e; // epsilon value for deciding when done.
Then the algorithm is straightforward:
Store the previous sum.
Compute the next sum.
Update n and compute the next factorial.
Check if the difference in the new vs. old iteration exceeds epsilon.
The code:
do {
last = sum;
sum += 1/fact;
fact *= ++n;
} while(sum-last >= e);
You need to write a beginning C program. There are lots of sources on the interwebs for that, including how to get user input from the argc and argv variables. It looks like you are to use 0.00001f for epsilon if it is not entered. (Use that to get the program working before trying to get it to accept input.)
For computing the series, you will use a loop and some variables: sum, current_term, and n. In each loop iteration, compute the current_term using n, increment n, check if the current term is less than epsilon, and if not add the current_term to the sum.
The big pitfall to avoid here is computing integer division by mistake. For example, you will want to avoid expressions like 1/n. If you are going to use such an expression, use 1.0/n instead.
Well in fact this program is very similar to the ones given in the learning to Program in C by Deitel, well now to the point (the error can't be 0 cause e is a irrational number so it can't be calculated exactly) I have here a code that may be very useful for you.
#include <stdio.h>
/* Function Prototypes*/
long double eulerCalculator( float error, signed long int *iterations );
signed long int factorial( int j );
/* The main body of the program */
int main( void )
{
/*Variable declaration*/
float error;
signed long int iterations = 1;
printf( "Max Epsilon admited: " );
scanf( "%f", &error );
printf( "\n The Euler calculated is: %f\n", eulerCalculator( error, &iterations ) );
printf( "\n The last calculated fraction is: %f\n", factorial( iterations ) );
return 1;
}
long double eulerCalculator( float error, signed long int *iterations )
{
/* We declare the variables*/
long double n, ecalc;
/* We initialize result and e constant*/
ecalc = 1;
/* While the error is higher than than the calcualted different keep the loop */
do {
n = ( ( long double ) ( 1.0 / factorial( *iterations ) ) );
ecalc += n;
++*iterations;
} while ( error < n );
return ecalc;
}
signed long int factorial( signed long int j )
{
signed long int b = j - 1;
for (; b > 1; b--){
j *= b;
}
return j;
}
That summation symbol gives you a clue: you need a loop.
What's 0!? 1, of course. So your starting value for e is 1.
Next you'll write a loop for n from 1 to some larger value (infinity might suggest a while loop) where you calculate each successive term, see if its size exceeds your epsilon, and add it to the sum for e.
When your terms get smaller than your epsilon, stop the loop.
Don't worry about user input for now. Get your function working. Hard code an epsilon and see what happens when you change it. Leave the input for the last bit.
You'll need a good factorial function. (Not true - thanks to Mat for reminding me.)
Did you ask where the constant e comes from? And the series? The series is the Taylor series expansion for the exponential function. See any intro calculus text. And the constant e is simple the exponential function with exponent 1.
I've got a nice Java version working here, but I'm going to refrain from posting it. It looks just like the C function will, so I don't want to give it away.
UPDATE: Since you've shown yours, I'll show you mine:
package cruft;
/**
* MathConstant uses infinite series to calculate constants (e.g. Euler)
* #author Michael
* #link
* #since 10/7/12 12:24 PM
*/
public class MathConstant {
public static void main(String[] args) {
double epsilon = 1.0e-25;
System.out.println(String.format("e = %40.35f", e(epsilon)));
}
// value should be 2.71828182845904523536028747135266249775724709369995
// e = 2.718281828459045
public static double e(double epsilon) {
double euler = 1.0;
double term = 1.0;
int n = 1;
while (term > epsilon) {
term /= n++;
euler += term;
}
return euler;
}
}
But if you ever need a factorial function I'd recommend a table, memoization, and the gamma function over the naive student implementation. Google for those if you don't know what those are. Good luck.
Write a MAIN function and a FUNCTION to compute the approximate sum of the below series.
(n!)/(2n+1)! (from n=1 to infinity)
Within the MAIN function:
Read a variable EPSILON of type DOUBLE (desired accuracy) from
the standard input.
EPSILON is an extremely small positive number which is less than or equal to
to 10^(-6).
EPSILON value will be passed to the FUNCTION as an argument.
Within the FUNCTION:
In a do-while loop:
Continue adding up the terms until |Sn+1 - Sn| < EPSILON.
Sn is the sum of the first n-terms.
Sn+1 is the sum of the first (n+1)-terms.
When the desired accuracy EPSILON is reached print the SUM and the number
of TERMS added to the sum.
TEST the program with different EPSILON values (from 10^(-6) to 10^(-12))
one at a time.

Simplified vulgar fractions in C

"How to write an algorithm that, given a number n, prints out all the simplified vulgar fractions that have the denominator 1..n"
(I hope I could phrase it well, feel free to rephrase.)
Example: If n is 3, the output should be like "1/2 1/3 2/3"
We were talking about this question in the end of the last class. He showed us a solution and asked us to try to understand the code. Here it is:
#include<stdio.h>
void main()
{
int p,m,n,i,j,a,b;
p=7;
m=0;
n=1;
do
{
printf("%d/%d\n",m,n);
i=j=1;
for(b=2; b<=p; b++)
{
a=m*b/n+1;
if(a*j<b*i)
{
i=a;
j=b;
}
}
m=i;
n=j;
}
while(i<j);
}
I'm new to C and just learning to code, to be honest I couldn't figure out what this code does. And it also prints "0/1", I also wonder why that is, I think it shouldn't be printing that.
Here is my elementary approach to this problem:
#include <stdio.h>
int gcd(int a, int b) // Finds the GCD of two numbers.
{
int temp;
while (a) {
temp = a;
a = b % a;
b = temp;
}
return b;
}
int main(void)
{
int i, j;
for (i = 1; i <= 7; i++) // Denominator goes from 1 to 7
for (j = 1; j < i; j++) // Numerator goes from 1 to denominator
if (gcd(i, j) == 1)
printf("%d/%d ", j, i); // If the numerator and the denominator
// are coprimes then print the fraction
return 0;
}
"n" is 7 in both of the codes. I checked the execution times with much bigger numbers and my algorithm is faster than the other one. So I don't understand what the other code is for. Also any suggestions/corrections about my code is appreciated.
Your professor's code looks like it may have been purposely complicated, maybe as a learning exercise. If that's the case, I can't say I agree with the practice.
Your approach of nested for loops is exactly how I would have approached the solution.
And it also prints "0/1", I also wonder why that is, I think it shouldn't be printing that.
Simply put, it prints "0/1" because of this line:
printf("%d/%d\n",m,n);
The values m and n are initialized to 0 and 1 right before the do loop, so on the first pass it prints exactly that.
Your code is better than the first paste in a few ways. The loop over b is a crappy way of trying to find a common prime factor for m and n. But it only runs to b=7, so the first program can print 11/121 and other non-reduced fractions!
If the loop over b were properly coded, it would take O(sqrt(n)) time. Your gcd() (using the Euclidean Algorithm well) has O(log(n)) time.
The other code is exceptionally poorly written. Single-letter variables for non-idiomatic uses? void main()? No comments? Nobody should be expected to understand that code, and especially not learners.
Your code seems pretty competent - it's far clearer and cleaner than the other code and pretty much superior in every way. The only suggestion I would make is, firstly, you should take in N as user input from the console, to make rerunning the program for different values simpler, and you should also comment the GCD function explaining it's operations.

Resources