Thread: This is homework but I'm really stuck

  1. #1
    Registered User
    Join Date
    Sep 2005
    Posts
    5

    This is homework but I'm really stuck

    I'm in a C++.NET class, and last took math 20 years ago.

    I have a classmate that has shared with me the following code for a program designed to estimate e using

    e = 1 +1/1!+1/2!+ ..

    Please see their code, which works, but doesn't do what I want it to, sure I could just copy it, but I'm trying to learn by studying it.

    Code:
    int _tmain
    
    float e,
    float num,
    float num1;
    
    e = 1;
    num = 1;
    num1 = 1;
    
    while (num < 20 )
              {
               num1 = num1 * num;
               e = e + (1 / ( 1 * num1 ) );
               num = num + 1;
              }
    
    cout << "e =  " << e;
    
    return 0;
    Now what I want to be able to do is pretty much the same thing, except that I wanted instead of a constant in the while loop, I wanted the constant to be set by the user.

    Here was my code which I used against theirs to check the accuracy, but it isn't working right:

    Code:
    int _tmain()
    {
    
    float ulim; //Upper limit of the computation to be input by user
    float result; // The computation will return this value
    float counter; // Counter for while loop
    
    
    
    result = 1;
    counter = 1;
    
    cout << "Please enter the upper limit for this computation  ";
    cin >>ulim
    
    while (counter<ulim)
    
    	{
    	
    	ulim = ulim*counter;
    	result = result +( 1 / ( 1* ulim));
            counter = counter + 1;
    	}
    
    	cout << "Best estimate of e based upon input is:  " <<result;
    	
    
    	return 0;
    }
    Thank you in advance for taking the time to read this.

    After working on 4 new programming problems (I've managed to work out 2 of these) over the past 6 days, for a total of about 54 hours and countin (last week I didn't even know what a factorial is, but hours on Google, have changed that), I have tried so many things and it now results in total confusion when I work with any code...I want to learn, I want to put the work and get something from this, but I admit defeat, I don't know what I'm doing wrong and I could really use some help.

    I'm not sure if I am coming across correctly, but I hope someone can point out where I'm whrong and why, and assist me with what I need to do, I will learn so much better that way. Right now I am fighting discouragement after 54 hours and I feel stupid...

  2. #2
    Information Crocodile
    Join Date
    Dec 2004
    Posts
    204
    I dont think this loop will end

    Code:
    while (counter<ulim) // Endless loop see below
    
    	{
    	
    	ulim = ulim*counter; // Loop doesnt end becos your constantly
    increasing the size of ulim. So counter will always be less than ulim.
    If The first code is pretty much the same as your code. Then you should look at variable num1 you probably misplaced it somwhere.

  3. #3
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Ok lets look at a few things:

    e = 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + ...

    So we look at the denomitor: 0!, 1!, 2!, 3!, 4!, ...
    and then we expand them out: 1, 1, 2 * 1, 3 * 2 * 1, 4 * 3 * 2 * 1, ...

    So ulim should tell you how many iterations to do. Since the 0! kinda throws off the pattern we'll move that out of the loop so you get something like:
    Code:
    int main() // not _tmain()
    {
      float e = 1; // 1/0! == 1
      unsigned fact = 1;  // 0! == 1, unsigned so we can use bigger values
      int ulim; // make this an int, not a float
    
      cout << "Please enter the upper limit for this computation  ";
      cin >>ulim; // you forgot the ;
      
      for (int count = 1; count < ulim; count++) // start from 1 since we already did one iteration, also makes the body of the loop easier
      {
        fact = fact * count;  // every iteration causes count to increment so we just multiple the new value of count with the old value of fact to get the factorial
        // fact *= count; another way you could have written the above line
        e = e + 1.0 / fact; 
        // e += 1.0 / fact;  another way you could have written the above line
      }
    
      cout << "Best guess: "<< e << endl;
    }
    Hope that helps

    Edit: Also of importance: Remember that factorial gets really big, really fast so if the user inputs say 10000 as the number of iterations then you'll easily exceed the amount an interger can be expected to hold

  4. #4
    aoeuhtns
    Join Date
    Jul 2005
    Posts
    581
    Then use a double for fact.

    But note that before factorial overflows 32 bits, you've reached the precision limit of a float anyway.

  5. #5
    Registered User
    Join Date
    Sep 2005
    Posts
    5
    Thank you so much - I really appreciated this assistance - your explanations were great, and I don't know what I would have done if not for your guidance.

    Please comment on the code below. I didn't realize that I had an infinte loop until you pointed it out. I had to use While, since for aren't covered in this chapter, only if and while...

    Code:
    #include "stdafx.h"
    #include <iostream>;
    using namespace std;
    
    int _tmain()
    {
    
    int ulim; //Upper limit of the computation to be input by user
    float e; // The computation will return this value
    int count; // Counter for while loop
    double fact; // factorial
    
    
    e = 1;
    count = 1;
    fact = 1;
    
    cout << "Please input the upper limit between 1- 10 for this factorial:  "; // here the user is prompted for the ulimit
    cin >>ulim;
    
    while (ulim >10)
    { 
    	cout << "Please enter in a number between 1-10.  This number is too high: "; //error checks for a number too high
    	cin >>ulim;
    }
    
    
    while (count < ulim) //As long as the count is less than the upper limit this loop will execute
    
    {
    	
    	fact = fact*count; //as count moves up it simulates the factorial moving up, since it increases to the upper limit
    	e = e+( 1 / ( 1* fact));  //e is set to 1, so it will build up to the upper limit each cycle thru the loop
            count += 1;  //adds one to count at the end of each cycle thru the loop till it equals ulim
    }
    
    cout << "Best estimate of e based upon input is:  " <<e;
    
    	return 0;
    }
    Last edited by shadowctr; 09-20-2005 at 12:43 PM.

  6. #6
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    why are you multipling by 1 here?
    Code:
    ( 1* fact)
    Code:
    cout << "Please input the upper limit between 1- 10 for this factorial:  "; // here the user is prompted for the ulimit
    cin >>ulim;
    
    while (ulim >10)
    { 
    cout << "Please enter in a number between 1-10.  This number is too high: "; //error checks for a number too high
    cin >>ulim;
    }
    A do {} while() loop would probably be more useful here. Also what happens if the user enters -1?

    Code:
    int _tmain()
    And your purpose of using _tmain() is what?

    As a general comment, you need to work on your indentation style.

  7. #7
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Quote Originally Posted by Rashakil Fol
    Then use a double for fact.

    But note that before factorial overflows 32 bits, you've reached the precision limit of a float anyway.
    Using a double would be a worse solution. By the time a 32 bit integer (esp an unsigned) nears the max value you are adding a negligible amount to e. The better option is to be aware of it and put preventative measures in place.

  8. #8
    Registered User
    Join Date
    Aug 2005
    Posts
    128
    Take this code for what it is, a modification of improved error checking of your input. Note that if a user enters a decimal number, it's treated as an int and the decimals are dropped.

    Code:
    #include <iostream>
    using namespace std;
    
    int main()
    {
    
    	int ulim = 1; //Upper limit of the computation to be input by user
    	float e = 1; // The computation will return this value
    	int count = 1; // Counter for while loop
    	double fact = 1; // factorial
    	int uservalue = 2; //2 used to indicate first time
    	string outline;
    
    
    	while (uservalue != 1)
    	{
    		if (uservalue == 0)
    		{ 
    			cout << ulim << " is not in range.  Please enter in a number between 1-10:";
    		}
    		else
    		{
    			cout << "Please enter in a number between 1-10: ";
    		}
    		                       
    		cin >> ulim;
    		if ((ulim <= 0)  || (ulim > 10))
    		{uservalue = 0;}
    		else
    		{uservalue = 1;}
    	}
    
    
    	while (count < ulim) //As long as the count is less than the upper limit this loop will execute
    
    	{
    		
    		fact = fact*count; //as count moves up it simulates the factorial moving up, since it increases to the upper limit
    		e = e+( 1 / ( 1* fact));  //e is set to 1, so it will build up to the upper limit each cycle thru the loop
    		count += 1;  //adds one to count at the end of each cycle thru the loop till it equals ulim
    	}
    
    	cout << "Best estimate of e based upon input is:  " <<e<<endl;
    
    	return 0;
    }

  9. #9
    aoeuhtns
    Join Date
    Jul 2005
    Posts
    581
    Quote Originally Posted by Thantos
    Using a double would be a worse solution. By the time a 32 bit integer (esp an unsigned) nears the max value you are adding a negligible amount to e. The better option is to be aware of it and put preventative measures in place.
    Do you read only the first sentence of people's replies?

  10. #10
    Registered User
    Join Date
    Aug 2005
    Posts
    128
    Do you believe in rhetorical questions?

  11. #11
    aoeuhtns
    Join Date
    Jul 2005
    Posts
    581
    Using a double when computing factorial is not bad. Factorials can be stored with no error up to larger values in a double than in a 32-bit integer, and what would overflow a 32-bit integer causes no problems with a double. The number will just get converted to a double anyway when you divide it under 1.0.

    It's true that if the user inputs 10000, a lot of unnecessary computation is performed, but the whole fun of this program is being able to input whatever you want and see how the accuracy changes and whether it stops growing. (For extra fun, rewrite the program to reverse the order of addition and see how the answers change! :-))

  12. #12
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Quote Originally Posted by Rashakil Fol
    Do you read only the first sentence of people's replies?
    Actually I read your entire response, your point? Also the double will run out of precision at a lower value then a 32 bit unsigned int would overflow on.

  13. #13
    aoeuhtns
    Join Date
    Jul 2005
    Posts
    581
    Quote Originally Posted by Thantos
    Actually I read your entire response, your point? Also the double will run out of precision at a lower value then a 32 bit unsigned int would overflow on.
    This is incorrect. Because the mantissa of a double is 52 bits long, any integer that can be exactly represented in a 53 bit unsigned integer representation can be exactly represented by a double. And so can its negative. Doubles can represent anything that 54 bit signed integers can represent.

    Here's some C code (C in a C++ forum because I don't feel like dealing with setprecision and such) that shows this.

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    void showbits(void * p, size_t len) {
    
        unsigned char ch;
        int i;
    
        while (len --) {
            ch = *((unsigned char *) p)++;
            for (i = 0; i < 8; ++i) {
                putchar('0' + (ch & 1));
                ch >>= 1;
            }
        }
        return;
    }
    
    void drawline(double x) {
        printf("%17.0f ", x);
        /*  showbits(&x, sizeof(double));*/
            putchar('\n');
        return;
    }
    
    int main(void) {
    
        double x = 1.0;
        int i;
        for (i = 0; i < 53; ++i) {
            x *= 2.0;
            drawline(x);
            drawline(x + 1.0);
            drawline(x + 2.0);
            drawline(x + 3.0);
            putchar('\n');
        }
    
        return 0;
    }
    If you want to see what the bits of the double look like, uncomment the call to the showbits subroutine. You might want a terminal wider than 80 characters for this, or modify the code to insert a newline character before the showbits call. Count the bits of the mantissa (or count the bits of the exponent and sign bit and subtract from 64) and you'll get 52. You'll see the very last group of numbers meet the limit of the double's precision. You'll be able to recognize the mantissa because the exponent keeps incrementing.

  14. #14
    the hat of redundancy hat nvoigt's Avatar
    Join Date
    Aug 2001
    Location
    Hannover, Germany
    Posts
    3,130
    To clear up some wordings:

    This is not C++.NET, aka Managed C++. This is normal C++ developed with Visual Studio.NET.

    _tmain is a Microsoft specific macro for UNICODE compilation and standard for Visual Studio.NET projects. It doesn't really make sense here, though.
    hth
    -nv

    She was so Blonde, she spent 20 minutes looking at the orange juice can because it said "Concentrate."

    When in doubt, read the FAQ.
    Then ask a smart question.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 6
    Last Post: 10-23-2006, 07:22 PM
  2. Homework
    By kermi3 in forum C Programming
    Replies: 10
    Last Post: 09-27-2001, 04:49 PM
  3. Homework
    By kermi3 in forum Windows Programming
    Replies: 5
    Last Post: 09-15-2001, 11:48 AM
  4. Homework
    By kermi3 in forum C Programming
    Replies: 0
    Last Post: 09-10-2001, 01:26 PM