446,413 Members | 998 Online Need help? Post your question and get tips & solutions from a community of 446,413 IT Pros & Developers. It's quick & easy.

# Steve Summit C notes , exercise

 P: n/a this is the programme i created, for exercise 2, assignment 3 at http://www.eskimo.com/~scs/cclass/asgn.beg/PS2.html it runs fine. i wanted to know if it needs any improvement: ----------------- PROGRAMME ---------------------------- /* Steve Summit's C programming Section 3 :: exercise 2 STATEMENT: Write a program to compute the average of the ten numbers 1, 4, 9, ..., 81, 100, that is, the average of the squares of the numbers from 1 to 10. (This will be a simple modification of Exercise 3 from last week: instead of printing each square as it is computed, add it in to a variable sum which keeps track of the sum of all the squares, and then at the end, divide the sum variable by the number of numbers summed.) */ #include #define DIVISOR 10 int main() { int i; double sum; sum = 0; for(i = 0; i <= 10; ++i) sum += i*i; printf("the average is: %.1f\n", sum / DIVISOR); return 0; } ----------------------- OUTPUT ---------------------- [arch@voodo steve-summit]\$ gcc -std=c99 -pedantic -Wall -Wextra assign-3_ex-2.c [arch@voodo steve-summit]\$ ./a.out the average is: 38.5 [arch@voodo steve-summit]\$ Mar 17 '07 #1
26 Replies

 P: n/a arnuld said: #include #define DIVISOR 10 int main() { int i; double sum; sum = 0; for(i = 0; i <= 10; ++i) sum += i*i; The loop iterates i through these values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, and 10. Now, 1 to 10 clearly gives us ten values, and 0 gives us an eleventh, so DIVISOR should surely be 11, not 10? -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at the above domain, - www. Mar 17 '07 #2

 P: n/a On Mar 17, 11:57 am, Richard Heathfield

 P: n/a arnuld wrote: it runs fine. i wanted to know if it needs any improvement: ----------------- PROGRAMME ---------------------------- /* Steve Summit's C programming Section 3 :: exercise 2 STATEMENT: Write a program to compute the average of the ten numbers 1, 4, 9, ..., 81, 100, that is, the average of the squares of the numbers from 1 to 10. /* Since the sum of the squares of the integers 1 ... N is N * (N + 1) * (2*N + 1) / 6, and there are N integers in 1 ... N, we have the following general function. It could be a macro, instead. Note the decimal points (there's one extra one not needed). If the function is not required to work except with N==10, replace the returned expression with 38.5 */ #include

 P: n/a Richard Heathfield wrote: arnuld said: >#include #define DIVISOR 10int main(){ int i; double sum; sum = 0; for(i = 0; i <= 10; ++i) sum += i*i; The loop iterates i through these values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, and 10. Now, 1 to 10 clearly gives us ten values, and 0 gives us an eleventh, so DIVISOR should surely be 11, not 10? The problem was for 1 ... 10. His starting with 0 does not affect the result; it just adds a (very small) time-wasting NOP. Mar 17 '07 #5

 P: n/a Martin Ambuhl wrote: arnuld wrote: >it runs fine. i wanted to know if it needs any improvement:----------------- PROGRAMME ----------------------------/* Steve Summit's C programmingSection 3 :: exercise 2STATEMENT:Write a program to compute the average of the ten numbers 1, 4,9, ..., 81, 100,that is, the average of the squares of the numbers from 1 to 10. /* Since the sum of the squares of the integers 1 ... N is N * (N + 1) * (2*N + 1) / 6, and there are N integers in 1 ... N, we have the following general function. It could be a macro, instead. Note the decimal points (there's one extra one not needed). If the function is not required to work except with N==10, replace the returned expression with 38.5 */ #include /& To satisfy the requirements of the program, you need only : int main(void) { average_of_squares(10); return 0; } but showing the value computed is probably a good idea: */ int main(void) { printf("The average is %g\n", average_of_squares(10)); return 0; } Mar 17 '07 #7

 P: n/a arnuld wrote: this is the programme i created, for exercise 2, assignment 3 at http://www.eskimo.com/~scs/cclass/asgn.beg/PS2.html it runs fine. i wanted to know if it needs any improvement: ----------------- PROGRAMME ---------------------------- /* Steve Summit's C programming Section 3 :: exercise 2 STATEMENT: Write a program to compute the average of the ten numbers 1, 4, 9, ..., 81, 100, that is, the average of the squares of the numbers from 1 to 10. (This will be a simple modification of Exercise 3 from last week: instead of printing each square as it is computed, add it in to a variable sum which keeps track of the sum of all the squares, and then at the end, divide the sum variable by the number of numbers summed.) */ #include #define DIVISOR 10 int main() { int i; double sum; You can probably make this an int. The square of an int is still an int (providing no overflows). It's generally faster using ints than doubles. > sum = 0; for(i = 0; i <= 10; ++i) To make your code portable, some might say to use for (i=1; i<=DIVISOR; i++) the ordering of ++i or i++ doesn't matter here. sum += i*i; printf("the average is: %.1f\n", sum / DIVISOR); if you take my advice above about using an int above, just be careful to promote sum to a float here, e.g. (float)sum / DIVISOR > return 0; } ----------------------- OUTPUT ---------------------- [arch@voodo steve-summit]\$ gcc -std=c99 -pedantic -Wall -Wextra assign-3_ex-2.c [arch@voodo steve-summit]\$ ./a.out the average is: 38.5 [arch@voodo steve-summit]\$ Mar 17 '07 #8

 P: n/a Jason Curl wrote: arnuld wrote: >this is the programme i created, for exercise 2, assignment 3 at http://www.eskimo.com/~scs/cclass/asgn.beg/PS2.htmlit runs fine. i wanted to know if it needs any improvement:----------------- PROGRAMME ----------------------------/* Steve Summit's C programmingSection 3 :: exercise 2STATEMENT:Write a program to compute the average of the ten numbers 1, 4,9, ..., 81, 100,that is, the average of the squares of the numbers from 1 to 10. (Thiswill be asimple modification of Exercise 3 from last week: instead of printingeach squareas it is computed, add it in to a variable sum which keeps track ofthe sum of allthe squares, and then at the end, divide the sum variable by thenumber of numbers summed.)*/#include #define DIVISOR 10int main(){ int i; double sum; You can probably make this an int. The square of an int is still an int (providing no overflows). It's generally faster using ints than doubles. >> sum = 0; for(i = 0; i <= 10; ++i) To make your code portable, some might say to use for (i=1; i<=DIVISOR; i++) Sorry - I meant to say 'Maintainable' not portable. > the ordering of ++i or i++ doesn't matter here. > sum += i*i; printf("the average is: %.1f\n", sum / DIVISOR); if you take my advice above about using an int above, just be careful to promote sum to a float here, e.g. (float)sum / DIVISOR >> return 0;}----------------------- OUTPUT ----------------------[arch@voodo steve-summit]\$ gcc -std=c99 -pedantic -Wall -Wextraassign-3_ex-2.c[arch@voodo steve-summit]\$ ./a.outthe average is: 38.5[arch@voodo steve-summit]\$ Mar 17 '07 #9

 P: n/a On 16 Mar 2007 23:46:28 -0700, "arnuld" Write a program to compute the average of the ten numbers 1, 4, 9, ..., 81, 100, that is, the average of the squares of the numbers from 1 to 10. #include #define DIVISOR 10 int main() { int i; double sum; sum = 0; for(i = 0; i <= 10; ++i) sum += i*i; printf("the average is: %.1f\n", sum / DIVISOR); return 0;} I'd do it the following way: ANSI-C: #include #define NUMBERS 10 int main(void) { int i, sum; sum = 0; for(i = 1; i <= NUMBERS; ++i) sum += i*i; printf("The average is: %lf\n", (double) sum / NUMBERS); return 0; } C-99: #include #define NUMBERS 10 int main(void) { int sum = 0; for(int i = 1; i <= NUMBERS; ++i) sum += i*i; printf("The average is: %lf\n", (double) sum / NUMBERS); return 0; } -- E-mail: infosimple-linede Mar 17 '07 #10

 P: n/a Gregor H. said: printf("The average is: %lf\n", (double) sum / NUMBERS); This is legal C99 (in which %lf was codified) but not legal C90. -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at the above domain, - www. Mar 17 '07 #11

 P: n/a On Sat, 17 Mar 2007 16:25:59 +0000, Richard Heathfield > printf("The average is: %lf\n", (double) sum / NUMBERS); This is legal C99 (in which %lf was codified) but not legal C90. Thanx! I overlooked that. Did a copy&paste of the OP's original code... :-( ANSI-C: printf("The average is: %f\n", (double) sum / NUMBERS); G. H. -- E-mail: infosimple-linede Mar 17 '07 #12

 P: n/a On Sat, 17 Mar 2007 17:11:32 +0100, Gregor H. I'd do it the following way: ANSI-C: #include #define NUMBERS 10 int main(void) { int i, sum; sum = 0; for(i = 1; i <= NUMBERS; ++i) sum += i*i; printf("The average is: %f\n", (double) sum / NUMBERS); ^^ return 0;} G. H. -- E-mail: infosimple-linede Mar 17 '07 #13

 P: n/a Martin Ambuhl wrote: Richard Heathfield wrote: >arnuld said [original code lines restored]: >>#include #define DIVISOR 10int main(){ int i; double sum; sum = 0; for(i = 0; i <= 10; ++i) sum += i*i; printf("the average is: %.1f\n", sum / DIVISOR); return 0;} The loop iterates i through these values: 0, 1, 2, 3, 4, 5, 6, 7, 8,9, and 10. Now, 1 to 10 clearly gives us ten values, and 0 gives us aneleventh, so DIVISOR should surely be 11, not 10? The problem was for 1 ... 10. His starting with 0 does not affect the result; it just adds a (very small) time-wasting NOP. True, but if the intent of doing exercises is to learn to program well, rather than getting the correct answer to a simple exercise, then it helps to form habits that will support robustness of more complicated programs. In this case, I think it better that the program correspond semantically, rather than displaying the correct answer, so iterating from 1 to 10, rather than 0 to 10, gives a better solution, in terms of style supporting good techniques. Another thought: the value 10 is written twice in the program, both representing the same upper limit. Use the DRY principle -- Don't Repeat Yourself: for (i = 1; i <= DIVISOR; ++i) What about the name of the upper limit? Yes, it is used as a divisor, but the more fundamental usage is as the upper limit or number of values. I prefer to use the more fundamental name: #define NVALUES 10 /* number of values to be averaged */ then use it as both the for loop limit and divisor. -- Thad Mar 17 '07 #14

 P: n/a Jason Curl wrote: arnuld wrote: >#include #define DIVISOR 10int main(){ int i; double sum; You can probably make this an int. The square of an int is still an int (providing no overflows). It's generally faster using ints than doubles. It certainly is sufficient for this particular exercise, but speed shouldn't be an issue here. I consider it a matter of style. I would use double here for this type of simple program so that I don't have to worry about overflow with a larger limit or truncation on division. > printf("the average is: %.1f\n", sum / DIVISOR); if you take my advice above about using an int above, just be careful to promote sum to a float here, e.g. (float)sum / DIVISOR That works, but I use double as the preferred floating point type. If I choose float (or long double), it is for a specific reason. -- Thad Mar 17 '07 #15

 P: n/a arnuld wrote: this is the programme i created, for exercise 2, assignment 3 at http://www.eskimo.com/~scs/cclass/asgn.beg/PS2.html it runs fine. i wanted to know if it needs any improvement: ----------------- PROGRAMME ---------------------------- /* Steve Summit's C programming Section 3 :: exercise 2 STATEMENT: Write a program to compute the average of the ten numbers 1, 4, 9, ..., 81, 100, that is, the average of the squares of the numbers from 1 to 10. (This will be a simple modification of Exercise 3 from last week: instead of printing each square as it is computed, add it in to a variable sum which keeps track of the sum of all the squares, and then at the end, divide the sum variable by the number of numbers summed.) */ #include #define DIVISOR 10 int main() { int i; double sum; sum = 0; Just set sum to zero at initialisation. for(i = 0; i <= 10; ++i) i should probably start from 1. Also replace the hardcoded 10 with DIVISOR. That was it's purpose in the first place. sum += i*i; printf("the average is: %.1f\n", sum / DIVISOR); return 0; } Mar 17 '07 #16

 P: n/a On Mar 18, 12:12 am, "santosh"

 P: n/a arnuld wrote: On Mar 18, 12:12 am, "santosh"

 P: n/a Default User wrote: arnuld wrote: .... snip ... >>actually, my style is to FIRST declare all the variable and theninitialize them. That's not a particularly good style, and doesn't work well for aggregates. Actually that is an excellent style, which keeps the actual cost of such automatic scope initializations in evidence. -- Chuck F (cbfalconer at maineline dot net) Available for consulting/temporary embedded and systems. -- Posted via a free Usenet account from http://www.teranews.com Mar 18 '07 #19

 P: n/a CBFalconer wrote: Default User wrote: arnuld wrote: ... snip ... > actually, my style is to FIRST declare all the variable and then initialize them. That's not a particularly good style, and doesn't work well for aggregates. Actually that is an excellent style, which keeps the actual cost of such automatic scope initializations in evidence. To me, things that need initialization (other than for() control vars) should get it at declaration time. This cuts down on errors and improves maintenance. I'll differ with you on it and leave it at that. As veteran programmers, I'm unlikely to change your mind, and you're unlikely to change mine. Brian Mar 18 '07 #20

 P: n/a arnuld said: >On Mar 18, 12:12 am, "santosh"

 P: n/a On Mar 19, 8:26 am, Richard Heathfield

 P: n/a arnuld said: >On Mar 19, 8:26 am, Richard Heathfield A minor nit: if it doesn't happen at the time you define the object,it isn't initialisation, merely assignment. That isn't /quite/ thesame thing i did not get what you meant by *it* in "if it does nothappen" . The provision of the value. int x = 6; /* this is an initialisation - the object x is defined and gets the value 6, all in one step */ int y; /* this is a definition, but no initialisation is performed */ y = 42; /* this is an assignment - it is NOT an initialisation */ > >- there are things you can do in initialisation that you can't doin assignment. so what style you advise Richard ? Some people, including myself, prefer to ensure that all objects have a deterministic value at all possible times. Thus, on definition, they use initialisation either to give the object the value it requires or, if that value isn't yet available, to give the object a default value (typically 0 or -1 or NULL depending on the circumstances) whose only role is to ensure that the value ascribed is determinate (known). The value of this approach is that the behaviour of the program is deterministic even if you accidentally use an object's value before you've given it the value you intended - you'll almost certainly get the wrong answer, but at least you'll get an answer. Other people prefer to avoid what they see as unnecessary overhead, choosing instead to rely on their compiler to warn them of a reference to an object's value where no value has been written to that object, and it is indeed true that some compilers can sometimes do this. -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at the above domain, - www. Mar 20 '07 #23

 P: n/a On Mar 20, 11:27 am, Richard Heathfield

 P: n/a arnuld said: so i see, "always getting an answer, whether wrong/right" style will be good. I see it that way too. Of course, it does mean that you have to be able to tell the difference between a right answer and a wrong answer, but I think of that skill as an intrinsic part of programming anyway. -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at the above domain, - www. Mar 20 '07 #25

 P: n/a In article <7r******************************@bt.com>, Richard Heathfield Some people, including myself, prefer to ensure that all objects have adeterministic value at all possible times. Thus, on definition, theyuse initialisation either to give the object the value it requires or,if that value isn't yet available, to give the object a default value(typically 0 or -1 or NULL depending on the circumstances) whose onlyrole is to ensure that the value ascribed is determinate (known). Thevalue of this approach is that the behaviour of the program isdeterministic even if you accidentally use an object's value beforeyou've given it the value you intended - you'll almost certainly getthe wrong answer, but at least you'll get an answer. The utility here isn't in always getting an answer, but in always getting the *same* answer. Deterministic-but-wrong code is a lot easier to debug than nondeterministic code. dave (get it to fail reliably, and it's half fixed) -- Dave Vandervies dj******@csclub.uwaterloo.ca Hmmm, I know some folks are not at all disturbed by getting flamed, but it's not often I see someone actively try to jump into a fire. --Mike Wahler in comp.lang.c Mar 20 '07 #26

 P: n/a Dave Vandervies said: In article <7r******************************@bt.com>, Richard Heathfield >>Thevalue of this approach is that the behaviour of the program isdeterministic even if you accidentally use an object's value beforeyou've given it the value you intended - you'll almost certainly getthe wrong answer, but at least you'll get an answer. The utility here isn't in always getting an answer, but in always getting the *same* answer. Deterministic-but-wrong code is a lot easier to debug than nondeterministic code. Quite so. That's what I meant to say, and it's what I thought I'd said. It just isn't what I *actually* said. -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at the above domain, - www. Mar 20 '07 #27

### This discussion thread is closed

Replies have been disabled for this discussion. 