-
Mathematical problem with a template
Hi,
I have this template
Code:
template <class T> class dimensions
{
protected:
T m_xstart;
T m_xend;
T m_ystart;
T m_yend;
public:
inline T getxstart(){return m_xstart;}
inline T getxend(){return m_xend;}
inline T getystart(){return m_ystart;}
inline T getyend(){return m_yend;}
inline void setxstart(T xstart){m_xstart = xstart;}
inline void setxend(T xend){m_xend = xend;}
inline void setystart(T ystart){m_ystart = ystart;}
inline void setyend(T yend){m_yend = yend;}
inline double getaspectratio()
{
T width = m_xend - m_xstart;
T height = m_yend - m_ystart;
if (height)
return width / height;}
};
Now if I do the following:
Code:
dimensions<double> dim;
dim.setxstart(0);
dim.setxend(500);
dim.setystart(0);
dim.setyend(1000);
double ratio = dim.getaspectratio();
"ratio" is allways zero. I expect it to be 0.5. Why is this?
Thanks in advance
Juergen
-
Re: Mathematical problem with a template
Quote:
Originally Posted by AlionSolutions
"ratio" is allways zero. I expect it to be 0.5. Why is this?
How do you check the value?
- petter
-
Re: Mathematical problem with a template
Quote:
Originally Posted by AlionSolutions
Hi,
I have this template
There is a flaw in your template:
Code:
inline double getaspectratio()
{
T width = m_xend - m_xstart;
T height = m_yend - m_ystart;
if (height)
return width / height;
}
If the template is based on integers, this truncates the value. As a matter of fact, your template will not compile at all if it is templatized on a type that does not have an operator /, and if it cannot be converted to double.
Quote:
"ratio" is allways zero. I expect it to be 0.5. Why is this?
This will be my new motto:
Did you debug the program to figure out why you may be getting the value?
Regards,
Paul McKenzie
-
Re: Mathematical problem with a template
Yes I did debug the code and as I am using doubles for the template, in my opinion it must return 0.5.
No clue why it is not so. In the debugger I checked the return value of getaspectratio() and I checked the values in side the template function. All looks well. I still don't know ehere the problem is.
Thanks
Juergen
-
Re: Mathematical problem with a template
Now I changed the getaspectratio()-function in the following way:
Code:
inline double getaspectratio()
{
double width = m_xend - m_xstart;
double height = m_yend - m_ystart;
return width / height;}
Ok, now it returns another value, which amazes me much more:
0.4994994994995
Why is this? I expected a plain 0.5 ???
Thanks
Juergen
-
Re: Mathematical problem with a template
Welcome to the wonderful world if floating point math :eek:
Realize that 0.1 is a repeating binary pattern that can not be expressed in floating point format exactly. This is one reason why floading point numbers should never be compared for equality, and why different processors will return different values for the same calculation....
Now where did I send that space sattellite off to..... :confused: :confused: :D
-
Re: Mathematical problem with a template
Thanks CPUWizzard :wave:
Is there any way to get that fixed? I need the "correct" values for further calculations. I have a zoom/scroll function in a matrix implented using doubles and I wondered why those computed values have so many digits after the point. Now I know why... do I? Nope I don't. I thought floating point calculation is the most accurate way to compute and now I get to know that there are such "incorrect" values. Those things ruin my calculations. Do you have any idea how to compute precise ? :D
Greetings
Juergen
-
Re: Mathematical problem with a template
1) Floating point math is not exact. The only exact binary numbers are ones that are multiples of inverse powers of 2 (1/2, 1/4, 3/8, etc).
2) Going back to my point of the doubles in the template, what other types were you going to call the getaspectratio? I would have expected it to be coded like this:
Code:
inline T getaspectratio()
{
T width = m_xend - m_xstart;
T height = m_yend - m_ystart;
return width / height;
}
Now if T were a special type (maybe a 128-bit mathematical class type that represents a double), then this makes much more sense.
Regards,
Paul McKenzie
-
Re: Mathematical problem with a template
Quote:
Originally Posted by AlionSolutions
I thought floating point calculation is the most accurate way to compute
No it isn't. Financial institutions disallow programmers from using doubles to compute monetary or any financially based calculations. That's why those institutions still use COBOL, or if they must use C++, special fixed point or BCD libraries are used, never doubles.
Quote:
and now I get to know that there are such "incorrect" values. Those things ruin my calculations. Do you have any idea how to compute precise ?
How precise? If you can get by with some round-off error, then you can round off most numbers by adding 0.005 or something similar. If you need exact calculations, see the paragraph above.
Regards,
Paul McKenzie
-
Re: Mathematical problem with a template
Thanx to you too Paul,
yeah makes sense. Ok, but if you say that floating point math is not exact, what would you recommend for a mathematical calculation software for computing? I allmost thought about using integers for the calculation and splitting up the values. I did this before back then when I coded assembler on the Amiga, because I had no FPU. But I thought it would be clever to use the floats, now that we all have FPUs.
So what ? Use integers or is there another way to get precise floating point calculations?
Thanks again
Juergen
-
Re: Mathematical problem with a template
Quote:
Originally Posted by AlionSolutions
Do you have any idea how to compute precise ? :D
Aha. So you see why I coded the getaspectratio the way I did? What if you discover a great mathematical class that gives you exact calculations? Not only that the class has overloaded operator / to do division exactly.
You don't have to change a single line of code in the template, if you recode the getaspectratio the way I did. You just templatize on this new type. You then can use doubles if you want to, or use another class.
Regards,
Paul McKenzie
-
Re: Mathematical problem with a template
Quote:
Originally Posted by AlionSolutions
I allmost thought about using integers for the calculation and splitting up the values. I did this before back then when I coded assembler on the Amiga, because I had no FPU. But I thought it would be clever to use the floats, now that we all have FPUs.
It looks like you need to get back that old code, or use something like MFC's COleCurrency.
Regards,
Paul McKenzie
-
Re: Mathematical problem with a template
Quote:
Originally Posted by Paul McKenzie
No it isn't. Financial institutions disallow programmers from using doubles to compute monetary or any financially based calculations. That's why those institutions still use COBOL, or if they must use C++, special fixed point or BCD libraries are used, never doubles.
I haven't experienced this yet. I have worked on US Treasury bonds, MBS, Swaps and other Interest rate derivatives without any issues. It is true that there is a compromise on the degree of accuracy one gets but we were (and the clients) happy with the results.
We also used them for calculations involving numerical methods, which themselves are not very accurate.
To OP - you may be fine here, it is just that you may need a rounding (or some level of error acceptance) mechanism as Paul suggested. What I mean is 0.4994994994995 is not exactly 0.5 but it is more 0.5 than 0.499. There are 2 ways - either you take this value and do further calculations or delay the aspectratio calculation for later (division). For example if this:
Code:
getAspectRation()*someValue/someOtherValue
is what you are to do then postpone division to this expression, i.e. don't do:
Code:
0.4994994994995*someValue/someOtherValue
but do:
Code:
500/1000*someValue/someOtherValue
This may help reduce the error in the result a little bit.
-
Re: Mathematical problem with a template
Quote:
Originally Posted by exterminator
I haven't experienced this yet. I have worked on US Treasury bonds, MBS, Swaps and other Interest rate derivatives without any issues. It is true that there is a compromise on the degree of accuracy one gets but we were (and the clients) happy with the results.
If you work in the insurance industry, where exact monetary amounts are required, usage of doubles (or whatever the floating point type is) is forbidden. You cannot compromise anything, else the company is at risk for litigation. If your customer is supposed to be owed $40.45 and you calculate the amount as $40.43, those 2 pennies can get you in a lot of legal trouble.
I remember working for an insurance company, where one person used doubles to calculate some values using a formula that was developed by the actuaries. More often than not, the actuaries would compare the results of the program with a hand calculation, and the program calculations were almost always off. Multiply that 1 penny off by 1,000 (which many calculations call for), and you see the mess you can get yourself into.
Regards,
Paul McKenzie
-
Re: Mathematical problem with a template
Quote:
Originally Posted by AlionSolutions
Is there any way to get that fixed? I need the "correct" values for further calculations.
You can use boost::rational for exact computation.
However, your application most likely does not need it. A certain amount of error is acceptable in most applications, including virtually all scientific applications.
Jeff
-
Re: Mathematical problem with a template
Quote:
Originally Posted by AlionSolutions
Ok, now it returns another value, which amazes me much more:
0.4994994994995
All this talk about the accuracy of floating point math, although theoretically correct, is absolutely irrelevant in the context of the error the OP is seeing. Doubles have an accuracy of 15 (approx) digits, whereas this answer of 0.4994994994995 is wrong in the fourth digit.
If OP said that his answer was 0.499999999999905, then the above discussion makes sense. But when his answer is wrong in the fourth digit, it's a red herring.
Clearly there is something else going on here.
I tend to think that Wildfrog's first question, which remains unanswered, is the correct approach: How did you check the value of getaspectratio()? Are you printf'ing it? If so give us the format string. Are you certain that you are actually using the code you posted, or have you simplified and, and without testing the simplified code, have you made the incorrect assumption that the output remains the same? Are you actually outputting the value of "ratio", and are you outputting it while it is still in-scope?
Mike
-
Re: Mathematical problem with a template
Incidentally, I think AlionSolutions (the OP) might have edited his original post, and changed the code. Please don't do that. It makes it impossible to guess why the first version (which no one can see) returned an output of zero (0) while the changed version returned an output of 0.4994994994995
Mike
-
Re: Mathematical problem with a template
Thanx jfaust, but I'm afraid, my application WILL need it, because there's a lot of very complex floating point calculation going on. And I need to show the values in edit-fields. Now imagine using an application, where, when you zoom two simple steps into something, one or more of the edit fields show a value with many digits after the point.
1. The user would not expect that after zooming with an integer a zooming factor, that he gets a fractional result.
2. It would be a struggle to edit values for a user.
3. Rounding is not an option as it would affect the result.
Yepp, that's it. It does not really look like a source of fun and joy to code a own math-library, but I think I'll try it :D
Greetings
Juergen
-
Re: Mathematical problem with a template
Quote:
Originally Posted by MikeAThon
Incidentally, I think AlionSolutions (the OP) might have edited his original post, and changed the code. Please don't do that. It makes it impossible to guess why the first version (which no one can see) returned an output of zero (0) while the changed version returned an output of 0.4994994994995
Mike
Nope, I did not change anything. I frst posted a version that uses variables of the template data type T. Later (seperate post) I changed them to double.
Greetinx
Juergen
-
Re: Mathematical problem with a template
Quote:
Originally Posted by AlionSolutions
Nope, I did not change anything. I frst posted a version that uses variables of the template data type T. Later (seperate post) I changed them to double.
Ah, now I see the difference. In my mind I had already substituted the template type "T" with a "double", so I did not see the difference from your second version at once. Thanks.
Anyway, Wildfrog's first question remains unanswered: How are you checking the returned value of getaspectratio()?
Please also tell us if you have single-stepped into the function, and have confirmed that the erroneous value already appears before the function returns. (My guess is to the contrary, i.e., that it's completely correct inside the getaspectratio() function.)
Mike
-
Re: Mathematical problem with a template
Quote:
Originally Posted by MikeAThon
All this talk about the accuracy of floating point math, although theoretically correct, is absolutely irrelevant in the context of the error the OP is seeing. Doubles have an accuracy of 15 (approx) digits, whereas this answer of 0.4994994994995 is wrong in the fourth digit.
This is the value the debugger shows me for the result. I tested the floating point division of 500/ 1000 on another machine and it produces a slightly different result.
Quote:
Originally Posted by MikeAThon
I tend to think that Wildfrog's first question, which remains unanswered, is the correct approach: How did you check the value of getaspectratio()?
Please read the thread. I allready answered this before. I am using a debugger. And the BCB-debugger is able to show variable values in their current state as each debugger can. So I checked the value by evaluating the expression "width/height" inside getaspectratio() AND I checked the return value in the calling function. All those checks gave the value mentioned and not 0.5 as expected.
To set things a bit clearer: I need this for adjusting the aspect ratio of a portion of a 2 dimensional matrix to the aspect ratio of an output image. I do this to avoid stretching and deformation of the resulting image if the output aspect ratio differs from the matrix ratio.
I also have the possibility to zoom in and out and scroll across the matrix. With each computation the little errors of the floating point calculations sum up a bit until they again deform the image. So after each zoom or scroll step I have to adjust the ratio again, which again adds a bit of incorrectness. This ends up in a mess. I found several little workarounds to make it less bad, but they are not really perfect solutions.
Greetinx
Juergen
-
Re: Mathematical problem with a template
Although there is some amount of error inherent in floating point calculations, you can keep that error constant by avoiding operations that accumulate the error. For instance, to iterate over a range, calculate from the start using multiplication rather than incrementally adding values.
Jeff
-
Re: Mathematical problem with a template
Aww what a sh*t: Just stepped through the function again and saw that there was a flaw in the computation of the width and height values. They were only 499 and 999. This was because I computed them incorrectly. What a mess. Ok, it was my error :D SORRY!!!
Thanx for pointing me at my stupidity
Juergen
-
Re: Mathematical problem with a template
Quote:
Originally Posted by AlionSolutions
What a mess. Ok, it was my error :D SORRY!!!
If you're still intereseted in a fixed point library:
http://wiki.yak.net/675
Regards,
Paul McKenzie