Steve Summit C notes , exercise

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • arnuld

    #1

    Steve Summit C notes , exercise

    this is the programme i created, for exercise 2, assignment 3 at



    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 <stdio.h>

    #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]$

  • Richard Heathfield

    #2
    Re: Steve Summit C notes , exercise

    arnuld said:

    <snip>
    #include <stdio.h>
    >
    #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

    email: rjh at the above domain, - www.

    Comment

    • arnuld

      #3
      Re: Steve Summit C notes , exercise

      On Mar 17, 11:57 am, Richard Heathfield <r...@see.sig.i nvalidwrote:
      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?
      OOPS!, thanks

      i will start with "i = 1"

      Comment

      • Martin Ambuhl

        #4
        Re: Steve Summit C notes , exercise

        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 <stdio.h /* not needed for the problem as stated, but
        the actal program we will show the value
        computed. */

        inline double average_of_squa res(int n)
        {
        return (n + 1.) * (2. * n + 1) / 6.;
        }

        /& To satisfy the requirements of the program, you need only :

        int main(void)
        {
        average_of_squa res(10);
        return 0;
        }

        but showing the value computed is probably a good idea: */


        int main(void)
        {
        printf("The average is %g\n", average_of_squa res(10));
        return 0;
        }

        Comment

        • Martin Ambuhl

          #5
          Re: Steve Summit C notes , exercise

          Richard Heathfield wrote:
          arnuld said:
          >
          <snip>
          >
          >#include <stdio.h>
          >>
          >#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?
          The problem was for 1 ... 10. His starting with 0 does not affect the
          result; it just adds a (very small) time-wasting NOP.


          Comment

          • user923005

            #6
            Re: Steve Summit C notes , exercise

            /* 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.)
            *
            * I wrote it in a way that was fun for me. YMMV.
            */

            #include <stdio.h>
            #include <math.h>
            #include <assert.h>

            double geometricMean(s ize_t count, double vector[])
            {
            double sum = vector[0];
            size_t index;

            if (count == 0)
            return 0;
            for (index = 1; index < count; index++)
            sum *= vector[index];

            return pow(sum, 1.0 / count);
            }

            /* Ref: http://mathworld.wolfram.com/PowerMean.html */
            /* CANNOT be used on negative quantities! */
            double generalizedMean (double power, size_t count, double
            vector[])
            {
            size_t index;
            double sum = 0;

            if (count == 0)
            return 0;
            if (power == 0)
            sum = geometricMean(c ount, vector);
            else {
            for (index = 0; index < count; index++) {
            assert(vector[index] 0);
            sum += pow(vector[index], power);
            }
            sum /= count;
            sum = pow(sum, 1.0 / power);
            }
            return sum;
            }

            double arithmeticMean( size_t count, double vector[])
            {
            double sum = 0;
            size_t index;

            if (count == 0)
            return 0;
            for (index = 0; index < count; index++)
            sum += vector[index];

            return sum / count;
            }

            double harmonicMean(si ze_t count, double vector[])
            {
            double sum = 0;
            size_t index;

            if (count == 0)
            return 0;
            for (index = 0; index < count; index++)
            sum += 1.0 / vector[index];
            sum /= count;
            return 1.0 / sum;
            }

            double rmsMean(size_t count, double vector[])
            {
            double sum = 0;
            size_t index;

            if (count == 0)
            return 0;
            for (index = 0; index < count; index++)
            sum += vector[index] * vector[index];

            sum /= count;
            return sqrt(sum);
            }

            int main()
            {
            int i;
            double vector[10];

            for (i = 1; i <= 10; ++i) {
            vector[i - 1] = i * i;
            }

            printf("The Arithmetical average is: %.1f\n",
            generalizedMean (1.0, 10, vector));
            printf("Checkin g.............. .......: %.1f\n\n",
            arithmeticMean( 10, vector));
            printf("The Harmonic average is: %.1f\n",
            generalizedMean (-1.0, 10, vector));
            printf("Checkin g.............. .......: %.1f\n\n", harmonicMean(10 ,
            vector));
            printf("The Geometric average is: %.1f\n",
            generalizedMean (0.0, 10, vector));
            printf("Checkin g.............. .......: %.1f\n\n",
            geometricMean(1 0, vector));
            printf("The RootMeanSquare average is: %.1f\n",
            generalizedMean (2.0, 10, vector));
            printf("Checkin g.............. .......: %.1f\n\n", rmsMean(10,
            vector));

            return 0;
            }

            /*
            C:\tmp>cl average.c
            Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42
            for 80x86
            Copyright (C) Microsoft Corporation. All rights reserved.

            average.c
            Microsoft (R) Incremental Linker Version 8.00.50727.42
            Copyright (C) Microsoft Corporation. All rights reserved.

            /out:average.exe
            average.obj

            C:\tmp>average
            The Arithmetical average is: 38.5
            Checking....... ..............: 38.5

            The Harmonic average is: 6.5
            Checking....... ..............: 6.5

            The Geometric average is: 20.5
            Checking....... ..............: 20.5

            The RootMeanSquare average is: 50.3
            Checking....... ..............: 50.3

            */

            Comment

            • Jason Curl

              #7
              Re: Steve Summit C notes , exercise

              Martin Ambuhl wrote:
              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 <stdio.h /* not needed for the problem as stated, but
              the actal program we will show the value
              computed. */
              >
              inline double average_of_squa res(int n)
              {
              return (n + 1.) * (2. * n + 1) / 6.;
              }
              I believe for portable C, we don't want to use 'inline', unless you're
              using C99. And even then, when I read the spec the it is implementation
              defined (i.e. it might exist as a keyword and do nothing). Couldn't we
              expect the compiler to inline this for us anyway at higher optimisation
              levels?
              >
              /& To satisfy the requirements of the program, you need only :
              >
              int main(void)
              {
              average_of_squa res(10);
              return 0;
              }
              >
              but showing the value computed is probably a good idea: */
              >
              >
              int main(void)
              {
              printf("The average is %g\n", average_of_squa res(10));
              return 0;
              }

              Comment

              • Jason Curl

                #8
                Re: Steve Summit C notes , exercise

                arnuld wrote:
                this is the programme i created, for exercise 2, assignment 3 at
                >

                >
                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 <stdio.h>
                >
                #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]$
                >

                Comment

                • Jason Curl

                  #9
                  Re: Steve Summit C notes , exercise

                  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.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 <stdio.h>
                  >>
                  >#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++)
                  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 -Wextra
                  >assign-3_ex-2.c
                  >[arch@voodo steve-summit]$ ./a.out
                  >the average is: 38.5
                  >[arch@voodo steve-summit]$
                  >>

                  Comment

                  • Gregor H.

                    #10
                    Re: Steve Summit C notes , exercise

                    On 16 Mar 2007 23:46:28 -0700, "arnuld" <geek.arnuld@gm ail.comwrote:
                    >
                    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 <stdio.h>
                    >
                    #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 <stdio.h>

                    #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 <stdio.h>

                    #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: info<at>simple-line<Punkt>de

                    Comment

                    • Richard Heathfield

                      #11
                      Re: Steve Summit C notes , exercise

                      Gregor H. said:

                      <snip>
                      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

                      email: rjh at the above domain, - www.

                      Comment

                      • Gregor H.

                        #12
                        Re: Steve Summit C notes , exercise

                        On Sat, 17 Mar 2007 16:25:59 +0000, Richard Heathfield
                        <rjh@see.sig.in validwrote:
                        >>
                        > 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: info<at>simple-line<Punkt>de

                        Comment

                        • Gregor H.

                          #13
                          Re: Steve Summit C notes , exercise

                          On Sat, 17 Mar 2007 17:11:32 +0100, Gregor H. <nomail@invalid wrote:

                          A correction. The type specification for printf (in the ANSI-C program)
                          should read "%f" and not "%lf"!
                          >
                          I'd do it the following way:
                          >
                          ANSI-C:
                          >
                          #include <stdio.h>
                          >
                          #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: info<at>simple-line<Punkt>de

                          Comment

                          • Thad Smith

                            #14
                            Re: Steve Summit C notes , exercise

                            Martin Ambuhl wrote:
                            Richard Heathfield wrote:
                            >arnuld said [original code lines restored]:
                            >>#include <stdio.h>
                            >>>
                            >>#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;
                            >>>
                            >>}
                            >>
                            >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.
                            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

                            Comment

                            • Thad Smith

                              #15
                              Re: Steve Summit C notes , exercise

                              Jason Curl wrote:
                              arnuld wrote:
                              >#include <stdio.h>
                              >>
                              >#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.
                              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

                              Comment

                              Working...