Thread: math problem...?

  1. #1
    UpTooLate
    Join Date
    Feb 2008
    Location
    New York
    Posts
    32

    Question math problem...?

    I am experiencing a runtime error with this program.
    The problem is that if I want one of the weights to be .7 and the other to be .3, it will say there is an error. It should only be saying this if the weights do not equal 1.0, which they do!
    I know it's something in the "getWeightedGrade" function, but I can't figure out why it is giving me this error message. Otherwise the program runs just fine.

    Here is an example:
    "
    Student's Name: Amy
    Type of test? midterm
    Score? 99
    Weight? (in decimal form) : .3

    Type of test? final
    Score? 87
    Weight? (in decimal form): .7
    Weights are not balanced. Try again.
    Type of test? "



    Can someone help me?

    Code:
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Grade
    {
    	public:
    		string getID();
    		double getScore();
    		double getWeight();
    		void enterInfo();
    		double getWeightedGrade();
    		void showInfo();
    		void changeScore(double mCurve);
    	
    	private:
    		string ID;
    		double mScore;
    		double mWeight;
    			
    };
    
    class Student
    {
    	public:
    		string showName();
    		Grade getFirstGrade();
    		Grade getSecondGrade();
    		void enterInfo();
    		bool areGoodWeights();
    		double getAverageOfBothWeighted();
    		void curveBothGrades(double CBG);
    	
    	private:
    		string aName;
    		Grade firstGrade;
    		Grade secondGrade;
    };
    
    class Seminar
    {
    	public:
    		void enterInfo();
    		Student getBestStudent();
    		void showTheFinalGrades();
    		void applyCurve(double thePercentToCurve);
    	private:
    		Student firstStudent;
    		Student secondStudent;
    		Student thirdStudent;
    };
    
    int main ()
    {
    	Seminar EngLit ;
     	EngLit.enterInfo();
    	EngLit.showTheFinalGrades();
    	cout << "The student with the highest final grade is: " ;
    	cout << EngLit.getBestStudent().showName() << endl; 
    	cout << "Curve amount? ";
    	double theCurveAmount;
    	cin >> theCurveAmount;
    	EngLit.applyCurve(theCurveAmount);
    	EngLit.showTheFinalGrades();
    
    	return 0;
    }
    
    string Grade::getID()
    {
    	return ID;
    }
    
    double Grade::getScore()
    {
    	return mScore;
    }
    
    double Grade::getWeight()
    {
    	return mWeight;
    }
    
    void Grade::enterInfo()
    {
    	cout << "Type of test? ";
    	cin >> ID;
    	cout << "Score? ";
    	cin >> mScore;
    	cout << "Weight? (in decimal form): ";
    	cin >> mWeight;
    	cout << endl;
    }
    
    double Grade::getWeightedGrade()
    {
    	double temp;
    	temp = mScore * mWeight;
    	return temp;
    }
    
    void Grade::changeScore(double mCurve)
    {
    	mScore = mScore + (mScore * mCurve);
    }
    
    string Student::showName()
    {
    	return aName;
    }
    
    Grade Student::getFirstGrade()
    {
    	return firstGrade;
    }
    
    Grade Student::getSecondGrade()
    {
    	return secondGrade;
    }
    
    void Student::enterInfo()
    {
    	cout << "Student's name? ";
    	cin >> aName;
    	love:
    	firstGrade.enterInfo();
    	secondGrade.enterInfo();
    	if (! areGoodWeights())
    	{
    		cout << "Weights are not balanced. Try again." << endl;
    		goto love;
    	}
    }
    
    bool Student::areGoodWeights()
    {
    	if ((firstGrade.getWeight() + secondGrade.getWeight()) == 1.0)
    	{
    		return true;
    	}
    	else
    	{
    		return false;
    	}
    }
    
    double Student::getAverageOfBothWeighted()
    {
    	double temp;
    	temp = firstGrade.getWeightedGrade() + secondGrade.getWeightedGrade();
    	return temp;
    }	
    
    void Student::curveBothGrades(double CBG)
    {
    	firstGrade.changeScore(CBG);
    	secondGrade.changeScore(CBG);
    }
    
    
    
    void Seminar::enterInfo()
    {
    	firstStudent.enterInfo();
    	secondStudent.enterInfo();
    	thirdStudent.enterInfo();
    }
    
    Student Seminar::getBestStudent()
    {
    	if (firstStudent.getAverageOfBothWeighted() > secondStudent.getAverageOfBothWeighted() && firstStudent.getAverageOfBothWeighted() > thirdStudent.getAverageOfBothWeighted())
    	{
    		return firstStudent;
    	}
    	else if (secondStudent.getAverageOfBothWeighted() > firstStudent.getAverageOfBothWeighted() && secondStudent.getAverageOfBothWeighted() > thirdStudent.getAverageOfBothWeighted())
    	{
    		return secondStudent;
    	}
    	else
    	{
    		return thirdStudent;
    	}
    }
    
    void Seminar::showTheFinalGrades()
    {
    	cout << "Final Grades: " << endl;
    	cout << firstStudent.showName() << "\t" << firstStudent.getAverageOfBothWeighted() << endl;
    	cout << secondStudent.showName() << "\t" << secondStudent.getAverageOfBothWeighted() << endl;
    	cout << thirdStudent.showName() << "\t" << thirdStudent.getAverageOfBothWeighted() << endl;
    }
    
    void Seminar::applyCurve(double thePercentToCurve)
    {
    	firstStudent.curveBothGrades(thePercentToCurve);
    	secondStudent.curveBothGrades(thePercentToCurve);
    	thirdStudent.curveBothGrades(thePercentToCurve);
    }

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Because floating point numbers are just approximations, you shouldn't compare them for equality. There is no guarantee that 0.3 + 0.7 == 1.0 because neither 0,3 nor 0.7 can be represented exactly.

    Instead you might test whether the difference is within some allowable error range:
    Code:
    #include <cmath>
    
    bool Student::areGoodWeights()
    {
    	return fabs(firstGrade.getWeight() + secondGrade.getWeight() - 1.0) < 0.000001;
    }
    You might probably also calculate the second weight for the user?
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #3
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    it's worth trying something like 0.30 and 0.70

    but in your case you should probably just use ints!

  4. #4
    Registered User guesst's Avatar
    Join Date
    Feb 2008
    Location
    Lehi, UT
    Posts
    179
    using ints (multiplied up) is for DOS. now-a-days there's no reason to be afraid of floating point numbers, every processor since the penitum can handle them.

    But anon is right, they are at their root imprecise, so you have to work within a certian range, even when dealing with equality.

    Let's do a classic, somewhat "contriversial" example.
    1/3 + 2/3 = 3/3 or 1, right? But:
    .3333333...+.6666666...=.9999999...
    So .9999999... = 1 right?
    obviously not, but within a certian tolerance, yes.
    Type-ins are back! Visit Cymon's Games at http://www.cymonsgames.com for a new game every week!

  5. #5
    Registered User Stonehambey's Avatar
    Join Date
    Jan 2008
    Location
    Kent, UK
    Posts
    118
    Quote Originally Posted by guesst View Post
    Let's do a classic, somewhat "contriversial" example.
    1/3 + 2/3 = 3/3 or 1, right? But:
    .3333333...+.6666666...=.9999999...
    So .9999999... = 1 right?
    obviously not, but within a certian tolerance, yes.
    There is a better method for showing this;

    Let x = 0.999...

    10x = 9.999...

    9x = 10x - x = (9.999...) - (0.999...) = 9

    x = 1

    But most computers can't store an infinite number of decimal pts ^_^

  6. #6
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    what i don't understand here is why everyone keeps talking about imprecision, but we're only dealing with 1 significant digit here. that is well within the precision of the mantissa. if i add two floats, 0.7 and 0.3, my program computes 1, not 1 + some number. roundoff error should not be a factor except at the least digit of precision...


    incidentally, i think the major problem here is actually the imposition that the weights must add to 1.

    that really serves no purpose. just calculate the averages as:

    sum(x[i]*w[i])/sum(w[i])

    rather than forcing the requirement that sum(w[i])==1.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Well yeah, guesst's example is a bad one because 0.999... is indeed 1, and what was described is a possible proof, with the "obviously not" claim made without substantiation.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    UpTooLate
    Join Date
    Feb 2008
    Location
    New York
    Posts
    32

    Thumbs up OH!!

    thanks guys!

  9. #9
    Registered User
    Join Date
    May 2008
    Posts
    53
    Quote Originally Posted by m37h0d View Post
    it's worth trying something like 0.30 and 0.70
    That isn't worth much: adding zeros at the end of floating point constants doesn't make them more precise.

    To someone new to computer programming coming from a science or engineering background, it takes some time to swallow that to the computer 0.3 == 0.30 == 0.300000... whereas in science and engineering, the extra zeros certainly have a meaning.

    --
    Computer Programming: An Introduction for the Scientifically Inclined

  10. #10
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    0.3 and 0.7 are representable in base 10, but not in base 2.

    http://wikipedia.com/wiki/Floating_point

    It's like how 1/3 is representable in base 3, but not base 10.

  11. #11
    Registered User guesst's Avatar
    Join Date
    Feb 2008
    Location
    Lehi, UT
    Posts
    179
    Quote Originally Posted by laserlight View Post
    Well yeah, guesst's example is a bad one because 0.999... is indeed 1, and what was described is a possible proof, with the "obviously not" claim made without substantiation.
    Well, no, it is obvious that 0.999999... is not 1, just look at them. Ask any 2nd grade student if they are the same. They're not. Obviously.

    Unless you're speaking mathematicly, and even then there's debate. But I go by the argument that .999999... behaves exactly like 1, so for all intents and purposes, dispite the representational differences between the two, they are the same.
    Type-ins are back! Visit Cymon's Games at http://www.cymonsgames.com for a new game every week!

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Well, no, it is obvious that 0.999999... is not 1, just look at them. Ask any 2nd grade student if they are the same. They're not. Obviously.
    Oh, okay. I get what you mean. You are saying that it is not the same as 1 in the same way that 1/2 is not the same as 2/4. That's fine.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User guesst's Avatar
    Join Date
    Feb 2008
    Location
    Lehi, UT
    Posts
    179
    Quote Originally Posted by laserlight View Post
    Oh, okay. I get what you mean. You are saying that it is not the same as 1 in the same way that 1/2 is not the same as 2/4. That's fine.
    *laf* Yeah, I guess so. And in a way that's entirely accurate to what I assert. I mean 1/2 doesn't look like 2/4, but it behaves exactly the same.

    But there are those I've met, mathematicians, who will assert that .9999... and 1 are not, in fact, the same because there is a difference of 10^(-infinity). They will assure you that it is not an insignificant difference, tho even they'd be hard pressed to find an example where it isn't.
    Type-ins are back! Visit Cymon's Games at http://www.cymonsgames.com for a new game every week!

  14. #14
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    So they just ignore all the proofs that show that .9999 is equivalent to 1?

  15. #15
    Registered User Stonehambey's Avatar
    Join Date
    Jan 2008
    Location
    Kent, UK
    Posts
    118
    Quote Originally Posted by guesst View Post
    But there are those I've met, mathematicians, who will assert that .9999... and 1 are not, in fact, the same because there is a difference of 10^(-infinity). They will assure you that it is not an insignificant difference, tho even they'd be hard pressed to find an example where it isn't.
    Then the people you speak of are not mathematicians. I've already proven they're the same number in this thread

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  2. Help!!c problem in math
    By feelsunny in forum Tech Board
    Replies: 2
    Last Post: 10-06-2007, 03:35 AM
  3. Math Problem....
    By NANO in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 11-11-2002, 04:37 AM
  4. math problem
    By unixOZ in forum Linux Programming
    Replies: 4
    Last Post: 10-19-2002, 12:17 AM
  5. Little math problem
    By Thantos in forum A Brief History of Cprogramming.com
    Replies: 2
    Last Post: 10-27-2001, 07:44 PM