Thread: Glass Rod Problem

  1. #1
    Registered User
    Join Date
    Jun 2012
    Posts
    15

    Glass Rod Problem

    I'm working on a project, and can't seem to get the project to get the triangle variable to increase when the conditions are met. I need this number to be accurate so I can work out the probability. Below you'll find the project, and my amateurish code. Any help is appreciated.




    Problem
    Experiments that are either too expensive or too dangerous to perform are often simulated on a computer when the computer is able to provide a good representation of the experiment. Find out how to call the random-number generator (usually a function returning a floating point value in the range 0 to 1) for your C++ system. (Look up the functions rand and srand in the library cstdlib on the website cplusplus.com). Write a program that uses the random-number generator to simulate the dropping of glass rods that break into three pieces. The purpose of the experiment is to estimate the probability that the lengths of the three pieces are such that they might form the sides of a triangle.
    For the purposes of this experiment, you may assume that the glass rod always breaks into three pieces. If you use the line segment 0 to 1 (on the real number line) as a mathematical model of the glass rod, a random-number generator (function) can be used to generate two numbers between 0 and 1 representing the coordinates of the breaks. The triangle inequality (the sum of the lengths of two sides of a triangle are always greater than the length of the third side) may be used to test the length of each piece against the lengths of the other two pieces.
    To estimate the probability that the pieces of the rod form a triangle, you’ll need to repeat the experiment many times and count the number of times a triangle can be formed from the pieces. The probability estimate is the number of successes divided by the total number of rods dropped. Your program should prompt the user for the number of rods to drop and allow the experiment to be repeated. Use a sentinel value of 21 to hale execution of the program.


    Code:
    Code:
    #include <iostream>
    #include <cmath>
    #include <cstdlib>
    #include <cfloat>
    #include <iomanip>
    #include <stdlib.h>
    #include <time.h>
    
    
    using namespace std;
    
    
    float doBreak (float, float);
    float doProbability (float, float);
    
    
    const int SENTINEL = 21;        //sentinal value
    
    
    int main()
    {
        float break1;
        float break2;
        float side1;
        float side2;
        float side3;
        float count;
        float tests;
        float triangle;
        float probability;
    
    
        const int SENTINEL = 21;
        count = 1;
        srand (time (NULL));
    
    
        cout << "Enter number of glassrods to demolish (Enter 21 to end program): ";
        cin >> tests;
    
    
        if 
        (tests != SENTINEL)
        {
            do
            {
                doBreak(break1, break2);
                count++;
            }while (count <= tests);
    
    
        doProbability(triangle, tests);
        cout << "The probability that the broken glass rods will form a triangle is: " << probability << "%" << endl;
        }
        else
        {
                cout << "Aww, I was hoping to break stuff..." << endl;
        }
        return 0;
    }
    
    
    float doBreak
        (float break1, 
        float break2)
    {
        float side1;
        float side2;
        float side3;
        float triangle;
        triangle = 0;
            
        break1 = (float)rand()/RAND_MAX;
        break2 = (float)rand()/RAND_MAX;
        
        if (break1 < break2)
        {
            side1 = break1;
            side2 = (break2 - break1);
            side3 = 1 - break2;
        }
        else if (break2 < break1)
        {    
            side1 = break2;
            side2 = (break1 - break2);
            side3 = 1 - break1;
        }
        else
        {
            side1 = break1;
            side2 = break1;
            side3 = break1;
        }
        if
        ((side1 + side2) > side3 &&
        (side1 + side3) > side2 &&
        (side2 + side3) > side1)
        {
            triangle += 1;
            cout << triangle << endl;
        }
        return side1;
        return side2;
        return side3;
        return triangle;
    }
        
    float doProbability 
        (float triangle,
        float tests)
    {
        float probability;
    
    
        probability = (triangle / tests) * 100;
        return probability;
    }

  2. #2
    Registered User
    Join Date
    Mar 2011
    Posts
    596
    A couple problems at least:

    1) you are not looking at the returned value from the doBreak() function at all;

    2) you can't return a sequence of values like that in doBreak(). The 'return side1' statement ends the function right there
    at that point. 'side1' is the only value returned.

    The variables declared in main() and the variables declared in doBreak() are independant, they are local to those functions
    and have scope only in those functions.

    One solution is to make those variables global; declare them once, before main().
    then the function can assign values to any and all of them,
    and the values are available in main().
    Last edited by megafiddle; 06-25-2012 at 06:28 PM.

  3. #3
    Registered User
    Join Date
    Jun 2012
    Posts
    15
    Thank you, I moved the variable though and am still having the issue. I also cleaned up the returns in doBreak.

    Code:
    
    #include <iostream>
    #include <cmath>
    #include <cstdlib>
    #include <cfloat>
    #include <iomanip>
    #include <stdlib.h>
    #include <time.h>
    
    
    using namespace std;
    
    
    float doBreak ();
    float doProbability (float, float);
    
    
    const int SENTINEL = 21;		//sentinal value
    float triangle;
    
    
    int main()
    {
    	float count;
    	float tests;
    	float probability;
    
    
    	count = 1;
    	srand (time (NULL));
    
    
    	cout << "Enter number of glassrods to demolish (Enter " << SENTINEL << " to end program): ";
    	cin >> tests;
    
    
    	if 
    	(tests != SENTINEL)
    	{
    		do
    		{
    			doBreak();
    			count++;
    		}while (count <= tests);
    		
    	doProbability(triangle, tests);
    	cout << "The probability that the broken glass rods will form a triangle is: " << probability << "%" << endl;
    	}
    	else
    	{
    			cout << "Aww, I was hoping to break stuff..." << endl;
    	}
    	return 0;
    }
    
    
    float doBreak()
    {
    	float break1;
    	float break2;	
    	float side1;
    	float side2;
    	float side3;
    	triangle = 0;
    	
    		
    	break1 = (float)rand()/RAND_MAX;
    	break2 = (float)rand()/RAND_MAX;
    	
    	if (break1 < break2)
    	{
    		side1 = break1;
    		side2 = (break2 - break1);
    		side3 = 1 - break2;
    	}
    	else
    	{	
    		side1 = break2;
    		side2 = (break1 - break2);
    		side3 = 1 - break1;
    	}
    	if
    	((side1 + side2) > side3 &&
    	(side1 + side3) > side2 &&
    	(side2 + side3) > side1)
    	{
    		triangle += 1;
    		cout << triangle << endl;
    	}
    	return triangle;
    }
    	
    float doProbability 
    	(float triangle,
    	float tests)
    	
    {
    	float probability;
    	
    	probability = (triangle / tests) * 100;
    	return probability;
    }

  4. #4
    Registered User
    Join Date
    Mar 2011
    Posts
    596
    Your doBreak() function returns 'triangle', so you need to look at it when you call doBreak().

    like this:

    triangle = doBreak();

    Also same for doProbability(triangle, tests);
    should be:

    probability = doProbability(triangle, tests);
    Last edited by megafiddle; 06-25-2012 at 07:24 PM.

  5. #5
    Registered User
    Join Date
    Jun 2012
    Posts
    15
    I feel dumb, I should have known that. That being said, I'm still getting off percentages because the triangle variable is not increasing.

    Code:
    #include <iostream>
    #include <cmath>
    #include <cstdlib>
    #include <cfloat>
    #include <iomanip>
    #include <stdlib.h>
    #include <time.h>
    
    
    using namespace std;
    
    
    float doBreak ();
    float doProbability (float, float);
    
    
    const int SENTINEL = 21;		//sentinal value
    float triangle;
    
    
    int main()
    {
    	float count;
    	float tests;
    	float probability;
    
    
    	count = 1;
    	srand (time (NULL));
    
    
    	cout << "Enter number of glassrods to demolish (Enter " << SENTINEL << " to end program): ";
    	cin >> tests;
    
    
    	if 
    	(tests != SENTINEL)
    	{
    		do
    		{
    			triangle = doBreak();
    			count++;
    		}while (count <= tests);
    
    
    	probability = doProbability(triangle, tests);
    	cout << "The probability that the broken glass rods will form a triangle is: " << probability << "%" << endl;
    	}
    	else
    	{
    			cout << "Aww, I was hoping to break stuff..." << endl;
    	}
    	return 0;
    }
    
    
    float doBreak()
    {
    	float break1;
    	float break2;	
    	float side1;
    	float side2;
    	float side3;
    	triangle = 0;
    	
    		
    	break1 = (float)rand()/RAND_MAX;
    	break2 = (float)rand()/RAND_MAX;
    	
    	if (break1 < break2)
    	{
    		side1 = break1;
    		side2 = (break2 - break1);
    		side3 = 1 - break2;
    	}
    	else
    	{	
    		side1 = break2;
    		side2 = (break1 - break2);
    		side3 = 1 - break1;
    	}
    	if
    	((side1 + side2) > side3 &&
    	(side1 + side3) > side2 &&
    	(side2 + side3) > side1)
    	{
    		triangle += 1;
    		cout << triangle << endl;
    	}
    	return triangle;
    }
    	
    float doProbability 
    	(float triangle,
    	float tests)
    	
    {
    	float probability;
    	
    	probability = (triangle / tests) * 100;
    	return probability;
    }

  6. #6
    Registered User
    Join Date
    Mar 2011
    Posts
    596
    Looks like 'triangle' is being reset to zero each time doBreak is called. Then if a triangle is formed,
    it gets incremented to 1. So doBreak() always returns a 0 or 1, and in main(), triangle is always 0 or 1.

    Couple ways to fix:

    In main(), change

    triangle = doBreak();

    to

    triangle = triangle + doBreak();

    or

    in the doBreak() function, change

    triangle = 0;

    to

    static triangle = 0;

  7. #7
    Registered User
    Join Date
    Jun 2012
    Posts
    15
    Will moving triangle = 0 to int main before calling doBreak also work?

    Quote Originally Posted by megafiddle View Post
    Looks like 'triangle' is being reset to zero each time doBreak is called. Then if a triangle is formed,
    it gets incremented to 1. So doBreak() always returns a 0 or 1, and in main(), triangle is always 0 or 1.

    Couple ways to fix:

    In main(), change

    triangle = doBreak();

    to

    triangle = triangle + doBreak();

    or

    in the doBreak() function, change

    triangle = 0;

    to

    static triangle = 0;

  8. #8
    Registered User
    Join Date
    Jun 2012
    Posts
    15
    I should also ask if there's an 'easy' way to avoid using triangle as a global variable, and just pass it back and forth. I get points off for global variables.

  9. #9
    Registered User
    Join Date
    Jun 2012
    Posts
    15
    This seems to work, but I'm curious for the future how it could be better.

    Code:
    #include <iostream>
    #include <cmath>
    #include <cstdlib>
    #include <cfloat>
    #include <iomanip>
    #include <stdlib.h>
    #include <time.h>
    
    
    using namespace std;
    
    
    float doBreak ();
    float doProbability (float, float);
    
    
    const int SENTINEL = 21;		//sentinal value
    
    
    
    
    int main()
    {
    	float count;
    	float tests;
    	float probability;
    	float triangle;
    	triangle = 0;
    
    
    	count = 1;
    	srand (time (NULL));
    
    
    	cout << "Enter number of glassrods to demolish (Enter " << SENTINEL << " to end program): ";
    	cin >> tests;
    
    
    	if 
    	(tests != SENTINEL)
    	{
    		do
    		{
    			triangle = doBreak();
    			count++;
    		}while (count <= tests);
    
    
    	probability = doProbability(triangle, tests);
    	cout << "The probability that the broken glass rods will form a triangle is: " << probability << "%" << endl;
    	}
    	else
    	{
    			cout << "Aww, I was hoping to break stuff..." << endl;
    	}
    	return 0;
    }
    
    
    float doBreak()
    {
    	float break1;
    	float break2;	
    	float side1;
    	float side2;
    	float side3;
    	float triangle;
    	
    	
    		
    	break1 = (float)rand()/RAND_MAX;
    	break2 = (float)rand()/RAND_MAX;
    	
    	if (break1 < break2)
    	{
    		side1 = break1;
    		side2 = (break2 - break1);
    		side3 = 1 - break2;
    	}
    	else
    	{	
    		side1 = break2;
    		side2 = (break1 - break2);
    		side3 = 1 - break1;
    	}
    	if
    	((side1 + side2) > side3 &&
    	(side1 + side3) > side2 &&
    	(side2 + side3) > side1)
    	{
    		triangle += 1;
    	}
    	return triangle;
    }
    	
    float doProbability 
    	(float triangle,
    	float tests)
    	
    {
    	float probability;
    	
    	probability = (triangle / tests) * 100;
    	return probability;
    }

  10. #10
    Registered User
    Join Date
    Mar 2011
    Posts
    596
    Yes you can move triangle into main(). As now written, globals are not necessary;
    global variables just would have been one solution as originally written.

    Actually though, you are not passing it back and forth. main() will have it's own variable 'triangle'
    and doBreak() will have it's own also. What you are doing is retrieving the value of 'triangle' as
    it exists in doBreak() and assigning it to the variable 'triangle' in main. These two 'triangle' variables
    could just as easily have two different names; they are different variables.

    Still though, you need to accumulate the count value of 'triangle' like in the examples just above.

    Using a static declaration will do two things:
    first it will initialize 'triangle' to zero only once, at the beginning of program execution,
    and second, it will preserve the value of 'triangle' from one function call to the next, so
    it will accumulate the count.

    Or as in the very first example,

    triangle = triangle + doBreak();

    it accumulates the count right there in main().

  11. #11
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    I'd like to interject to say that I really like this thread, and that it sets a good example. The problem is clearly described by the poster (not just copy-paste from the problem statement). The problem statement itself is included. You posted code, and it was properly indented. People made observations and suggestions, and you implemented them, posting the changed code. You are listening to what people are saying and making progress. This is something we do not see enough of on this board. Thanks, and keep it up.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  12. #12
    Registered User
    Join Date
    Jun 2012
    Posts
    15
    I am going to attempt that new idea in my own time, though not tonight when I'm close doing it the long way! <g>

    This is where I'm at, and I'm very happy, thanks for the help. I'm taking it apart in my head to figure out a way to get around the triangle being declared in two places. Global would make sense, but as I said, the teacher dislikes them.

    Code:
    #include <iostream>
    #include <cmath>
    #include <cstdlib>
    #include <cfloat>
    #include <iomanip>
    #include <stdlib.h>
    #include <time.h>
    
    
    using namespace std;
    
    
    float doBreak ();
    float doProbability (float, float);
    
    
    const int SENTINEL = 21;		//sentinal value
    
    
    
    
    int main()
    {
    	float count;
    	float tests;
    	float probability;
    	float triangle;
    	
    
    
    	count = 1;
    	srand (time (NULL));
    
    
    	cout << "Enter number of glassrods to demolish (Enter " << SENTINEL << " to end program): ";
    	cin >> tests;
    
    
    	if 
    	(tests != SENTINEL)
    	{
    		do
    		{
    			triangle = doBreak();
    			count++;
    		}while (count <= tests);
    
    
    	probability = doProbability(triangle, tests);
    	cout << "The probability that the broken glass rods will form a triangle is: " << probability << "%" << endl;
    	}
    	else
    	{
    			cout << "Aww, I was hoping to break stuff..." << endl;
    	}
    	return 0;
    }
    
    
    float doBreak()
    {
    	float break1;
    	float break2;	
    	float side1;
    	float side2;
    	float side3;
    	float static triangle = 0;
    	
    	
    	
    		
    	break1 = (float)rand()/RAND_MAX;
    	break2 = (float)rand()/RAND_MAX;
    	
    	if (break1 < break2)
    	{
    		side1 = break1;
    		side2 = (break2 - break1);
    		side3 = 1 - break2;
    	}
    	else
    	{	
    		side1 = break2;
    		side2 = (break1 - break2);
    		side3 = 1 - break1;
    	}
    	if
    	((side1 + side2) > side3 &&
    	(side1 + side3) > side2 &&
    	(side2 + side3) > side1)
    	{
    		triangle += 1;
    	}
    	return triangle;
    }
    	
    float doProbability 
    	(float triangle,
    	float tests)
    	
    {
    	float probability;
    	
    	probability = (triangle / tests) * 100;
    	return probability;
    }

  13. #13
    Registered User
    Join Date
    Mar 2011
    Posts
    596
    Quote Originally Posted by CoryMore View Post
    This seems to work, but I'm curious for the future how it could be better.
    I would change this:

    const int SENTINEL = 21; //sentinal value

    to this:

    #define SENTINEL 21 //sentinal value

    as it doesn't need to be a variable.

    Also, you want:

    static float triangle = 0;
    Last edited by megafiddle; 06-25-2012 at 08:52 PM.

  14. #14
    Registered User
    Join Date
    Jun 2012
    Posts
    15
    I believe it is, after adding a print out:
    Code:
    if
    	((side1 + side2) > side3 &&
    	(side1 + side3) > side2 &&
    	(side2 + side3) > side1)
    	{
    		triangle += 1;
    		cout << triangle << endl;
    	}
    	return triangle;
    }
    I get:

    $ ./rods
    Enter number of glassrods to demolish (Enter 21 to end program): 100
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    The probability that the broken glass rods will form a triangle is: 30%

  15. #15
    Registered User
    Join Date
    Mar 2011
    Posts
    596
    Quote Originally Posted by brewbuck View Post
    I'd like to interject to say that I really like this thread, and that it sets a good example. The problem is clearly described by the poster (not just copy-paste from the problem statement). The problem statement itself is included. You posted code, and it was properly indented. People made observations and suggestions, and you implemented them, posting the changed code. You are listening to what people are saying and making progress. This is something we do not see enough of on this board. Thanks, and keep it up.
    I agree, it was a pleasure to help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sleep() function problem or logic problem?
    By FernandoBasso in forum C Programming
    Replies: 7
    Last Post: 11-16-2011, 05:50 PM
  2. Replies: 4
    Last Post: 10-16-2008, 07:30 PM
  3. syntax linked list problem & struct problem
    By beely in forum C Programming
    Replies: 5
    Last Post: 11-11-2002, 09:14 AM
  4. The glass is half full
    By dirkduck in forum A Brief History of Cprogramming.com
    Replies: 11
    Last Post: 03-30-2002, 03:08 PM