-
Divide By 0 & Overflow By Division handling / avoidance
For floating point numbers, you cannot avoid a divide by 0 merely by checking denominator != 0.0, since dividing by a small non-zero number can cause overflow (1 / 1e-309 = 1e+309 = overflow double). Note 1e-309 is within double range, as denormal numbers can store magnitudes much smaller than the smallest normal number (~1e-324 for double).
Note that the size limit of such a denominator causing an overflow is dependent on the size of the numerator. If the numerator is larger, the denominator needn't be as small (1e5 / 1e-308 = 1e+313 = overflow double).
So, once and for all: How do you deal with division by 0 and overflow by division for floating point numbers? The calculations required to avoid it will slow code considerably. It seems easier to just let it go, and check the result for NaN. Which leads to another question:
Is it ok to divide by unchecked input, and check for result == NaN? In other words, does this throw exceptions for certain compilers? How portable is this? Do any CPUs (including those other than Intel / AMD) respond in strange ways that I should know about?
-
Re: Divide by 0 avoidance / handling
Assuming that the overflow you are worried about does not occur often, then I would attempt to deal with this problem by surrounding the division operation with a try block, and throw an exception every time the quotient indicated an overflow. The check for an overflow condition would not be time consuming. In the event of an overflow, in your catch handler you would reset the quotient to some suitable number.
-
Re: Divide by 0 avoidance / handling
Thanks for your reply, spiritualfields.
My code should never produce overflows, if everything works correctly. But, I wish to make robust code.
Yes, checking the result (quotient), instead of checking the input, is exactly what I want to do (since checking the input can be complicated, accident prone, time consuming, and perhaps not portable).
How I deal with an overflow, once I've found one, is not my issue. (I will merely check if the result is NaN, and if so, I'll set it to be something reasonable.)
-
Re: Divide by 0 avoidance / handling
It looks like you can control the behaviour with _controlfp_s. It is "platform-independent", such that it runs on Intel (x86), MIPS, and ALPHA platforms. But, it can't be portable, since the leading underscore means it is a Microsoft extension. Thus, I assume "platform-independent" only means hardware that runs Windows.
The _controlfp_s article states: "The run-time libraries mask all floating-point exceptions by default", which is what I want; it
allows me to check for NaNs AFTER the operation, instead of attempting to avoid such operations (which is more costly).
So... Is masking all exceptions the standard default behaviour? Can I expect this for any hardware / compiler that I use? I would assume so...
Thanks for your time,
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by JasonD
So... Is masking all exceptions the standard default behaviour? Can I expect this for any hardware / compiler that I use? I would assume so...
No, you can't assume that... By default, floating point exceptions are turned on. It depends on the implementation of the floating point library you use - and the VC++ standard library happens to turn them off.
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by gstercken
No, you can't assume that... By default, floating point exceptions are turned on. It depends on the implementation of the floating point library you use - and the VC++ standard library happens to turn them off.
gstercken, ok, thanks -- this is what I needed to know. This raises more questions / concerns:
1. I probably shouldn't assume that future versions of the compiler / FP library will continue to behave like this (just in case). So, I should read the current state using Microsoft's functions, to confirm this (or modify it), as my code will assume such a state.
2. As for other compilers / architectures, for which Microsoft's functions do not exist, I'll have to put an explicit error at compile time to ensure that when such a compile occurs, that the programmer will know that to insert compiler / architecture specific code to ensure no exceptions are thrown -- as they may or may not also be shutting off exceptions by default, depending on their FP library.
3. I wonder if exceptions can be shut off for ANY given architecture? Do any exist that do NOT support masking exceptions? It wouldn't be good to port and find out I can't shut them off, when a lot of my code expects that they are shut off...
Thanks for the information! It is much appreciated.
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by JasonD
2. As for other compilers / architectures, for which Microsoft's functions do not exist, I'll have to put an explicit error at compile time to ensure that when such a compile occurs, that the programmer will know that to insert compiler / architecture specific code to ensure no exceptions are thrown
For Intel CPU's, you can write the inline assembly to turn off/on the floating point exceptions. That's all that control_fp is basically doing, and that is making assembly language calls. It is just a single line of assembly code
Code:
DWORD value = 0x0000003f;
_asm fldcw word ptr value
The "Load Control Word" instruction (fldcw) is what does the trick in masking the FPU exceptions (I've successfully used 0x0000003f). I believe that 0x0000003f sets the exception handling to the default state for Visual C++ apps. A long time ago I had to do this for some misbehaving third-party drivers that mess up the exception handling flags when loaded.
Here is a link to the FPU control word, and what the various flags are that you can set:
http://www.website.masmforum.com/tut...hap1.htm#cword
Of course different compilers have different ways of issuing assembly language instructions inline. But regardless of this, you turn on/off floating point by issuing an assembly language call to change the control status word, regardless of the compiler.
Regards,
Paul McKenzie
-
Re: Divide by 0 avoidance / handling
Paul, thanks for the assembly information. Personally, I would use Microsoft's function, instead, since, when you use the proper constants, you can know for sure what you are asking of the FPU, unlike you trying to remember what 0x0000003f means. But, thanks anyway. It's nice to know the implementations of such functions, and I am always interested in such things. :)
And thanks for the website. I understand this better now. If I follow correctly: The FPU's control word sets whether it handles exceptions itself (i.e. stores a NaN in the result, and continues on its merry way), or if generates an interrupt, instead. If it generates an interrupt, then this will execute some software code -- which could be anything. I assume by default, this code throws an exception. If unhandled, it will terminate the program, or you could catch it yourself. Or, with Microsoft's functions, you can set your own handling routine to be called when such an interrupt occurs.
Does this make sense?
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by JasonD
Paul, thanks for the assembly information. Personally, I would use Microsoft's function, instead, since, when you use the proper constants, you can know for sure what you are asking of the FPU, unlike you trying to remember what 0x0000003f means. But, thanks anyway.
You can use those same constants when setting the control word using assembly language. I just used 0x0000003f, since I know what bits in the control word I need to set.
Quote:
And thanks for the website. I understand this better now. If I follow correctly: The FPU's control word sets whether it handles exceptions itself (i.e. stores a NaN in the result, and continues on its merry way), or if generates an interrupt, instead. If it generates an interrupt, then this will execute some software code -- which could be anything. I assume by default, this code throws an exception. Yes, an exception is thrown and you're code can handle it. Otherwise, no exception is thrown If unhandled, it will terminate the program, or you could catch it yourself. Or, with Microsoft's functions, you can set your own handling routine to be called when such an interrupt occurs.
Yes, this is true. But again, for Windows, anything that you can do with Visual C++ can be done with any Windows C++ compiler, since Visual C++ sets up SEH (Structured Exception Handling), which is also generic Windows stuff, and not tied to any compiler.
Regards,
Paul McKenzie
-
Re: Divide by 0 avoidance / handling
I've never dealt with a problem such as the one you are trying to avoid, but I would if at all possible have my program handle it rather than rely on chip architecture and compiler idiosyncrocies. All C++ compilers at least have the same hierarcry of standard exceptions. overflow_error is one of the exceptions derived from runtime_error (which is derived from the overall base class of the hierarchy - exception). You should be able to handle the overflow by catching and handling exception objects of type overflow_error.
-
Re: Divide by 0 avoidance / handling
No one suggested std::numeric_limits<T>::epsilon()?
That is what you need - you should check the input if negative by adding std::numeric_limits<float>::epsilon() to see if it becomes positive and if input is positive by subtracting that value to see if it becomes negative. If it does then you can consider it to be 0 and restrict division - else you should not go ahead and may be throw an exception.
Another thing, there are various levels of exception guarantees that you can provide for your function. Even if you don't do anything and let the result of divide by zero be as it is, it should be responsibility of the caller to maintain the contract of the function, i.e. not passing a zero denominator.
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by spiritualfields
I've never dealt with a problem such as the one you are trying to avoid, but I would if at all possible have my program handle it rather than rely on chip architecture and compiler idiosyncrocies.
The problem is that if the floating point CPU (Intel) is set a certain way, the CPU may be handling many of the exceptions that you would normally get, so your program never gets the chance of handling or testing the exception logic, giving the false sense of security that your program is OK.
Believe it or not, there are many programs out there that crash when run with the CPU set to not handle the exceptions. The problem is exactly what I stated above -- the developers tested their program with the CPU's set to handle the exceptions without even being aware. So all the logic used to detect the exceptions never could be tested, but gives programmer the illusion that it was tested.
For example:
Code:
int main()
{
double d = 0.0;
double g = 1000.0 / d;
}
Compiled using Visual C++ 6.0, this does not throw an exception that your program can handle, because the CPU handled it and went on its merry way without you being aware anything wrong has happened. To have the exceptions handled by your app, you have to set the CPU's flags, either by control_fp() or setting the registers yourself using assembly language.
Of course this is outside the scope of the normal program that just needs to do math operations, but it is necessary to know how the floating point exceptions are handled at the chip level, at least for the Intel. If not you'll fall into the same problems as the developers I mentioned.
Regards,
Paul McKenzie
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by gstercken
By default, floating point exceptions are turned on.
I just found a webpage that states:
"By default, floating-point exceptions on the Intel architecture are disabled; instead, the floating-point library generates IEEE-compatible infinite results."
Do you know of any documentation I could refer to, to get an official answer for what the default behaviour is? What are your sources?
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by JasonD
I just found
a webpage that states:
"
By default, floating-point exceptions on the Intel architecture are disabled; instead, the floating-point library generates IEEE-compatible infinite results."
Do you know of any documentation I could refer to, to get an official answer for what the default behaviour is? What are your sources?
Depends on the C runtime library of the compiler. For all the Visual C++ compilers, the runtime library disables the floating point exceptions, and you must turn them on as the article describes (or you can turn them on by setting the FPU control word).
Regards,
Paul McKenzie
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by Paul McKenzie
... But again, for Windows, anything that you can do with Visual C++ can be done with any Windows C++ compiler...
Yes, of course.
My application will be compiled with VC++ .NET 2003 (v7.1) and be deployed on Windows systems. This implies it could run on whatever hardware can run Windows. So far, I know this means: Intel (x86), MIPS, and ALPHA platforms (is this correct? and are there any others?).
So my main concern is that my code will run properly at least on such hardware. (A secondary concern is portability.)
-
Re: Divide by 0 avoidance / handling
Your code will only run on MIPS and ALPHA platforms if you compile it for them. You cannot compile a Windows EXE on an x86 platform, and expect it to run on a MIPS platform, IIRC.
Viggy
-
Re: Divide by 0 avoidance / handling
Quote:
Compiled using Visual C++ 6.0, this does not throw an exception that your program can handle, because the CPU handled it and went on its merry way without you being aware anything wrong has happened. To have the exceptions handled by your app, you have to set the CPU's flags, either by control_fp() or setting the registers yourself using assembly language.
I never knew that. If I had been dealing with this problem, I would have created an overflow on testing, and then been scratching my head over why an exception wasn't getting thrown. I'm surprised that warnings about this sort of subversion (specifically with respect to arithmetic overflow) is not mentioned in the STL books. Josuttis doesn't even mention this, unless he put it in a little note that I missed. Thanks.
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by spiritualfields
I've never dealt with a problem such as the one you are trying to avoid, but I would if at all possible have my program handle it rather than rely on chip architecture and compiler idiosyncrasies. All C++ compilers at least have the same hierarchy of standard exceptions. overflow_error is one of the exceptions derived from runtime_error (which is derived from the overall base class of the hierarchy - exception). You should be able to handle the overflow by catching and handling exception objects of type overflow_error.
I follow your thoughts. The reason this thread started is because I want robust code. So, I am not going to rely on anything unreliable.
I was hoping that all FPUs handled such invalid operations in the same manner. I thought this may be so, since NaN and infinities are part of the IEEE standard. If they handle such cases, by far the easiest way to handle them is to let them happen, and check the result for NaN. This way, you need not be concerned that your assertion code is correct (again, denominator != 0.0 is insufficient). In fact, you could even let a bad operation carry through more operations, and only check the final result (i.e. just before you go to use it), instead of every division, so it would be faster. Also, there would be no overhead from exception handling.
I was unaware there were so many control options available to FPUs. If I can ensure that the FPU control word disallows interrupts / exceptions, and deals with them as the IEEE standard dictates, then I believe my code idea is the most reliable code of all. However, I am uncertain if I can ensure the FPU status... this is my problem.
Over in the microsoft.public.vc.language newsgroup, a real world story was told of the FPU status change causing unexpected crashes. The story appears to imply that the FPU status is not maintained per thread / process. Can this possibly be true? If the FPU status is global to the entire OS, then no software could ever rely on it. Thus, I find this hard to believe. Any thoughts / info on this?
Thanks for your time,
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by JasonD
Over in the microsoft.public.vc.language newsgroup, a real world story was told of the FPU status change causing unexpected crashes. The story appears to imply that the FPU status is not maintained per thread / process. Can this possibly be true?
Well, if it were true, then anytime you run a Visual C++ app, you change the FPU globally. I highly doubt it, but you can easily test it by running two apps under the debugger and watch the registers. One program calls control_fp() with some wacky values, and see if the FPU control status word of the other program changes.
What does happen, and I've experienced it, is that any code that relies on third-party software, i.e. loading of drivers, then there is your risk of having the FPU control word change on you. The HP printer drivers from some time back were notorious for changing the state of the FPU control word whenever they were used.
Regards,
Paul McKenzie
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by exterminator
No one suggested std::numeric_limits<T>::epsilon()?
That is what you need - you should check the input if negative by adding std::numeric_limits<float>::epsilon() to see if it becomes positive and if input is positive by subtracting that value to see if it becomes negative. If it does then you can consider it to be 0 and restrict division - else you should not go ahead and may be throw an exception.
std::numeric_limits<T>::epsilon() returns the difference between 1 and the smallest value greater than 1 that the data type can represent. There are similar constants defined in FLOAT.H:
Code:
#define FLT_EPSILON 1.192092896e-07F /* smallest such that 1.0+FLT_EPSILON != 1.0 */
#define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */
Firstly, your logic could be improved by only performing one check, instead of two: if (fabs(x) < epsilon) ... However, I don't follow your logic. I don't think it is correct.
I realize you can multiply a value with these epsilon values to know the smallest absolute change that you can make to this original value, and get a different floating point representation (i.e. the value actually changes). These tolerances are VERY meaningful in this manner. But, to avoid an overflow, you must also be aware of the size of the numerator; not just the denominator (as I have already stated). This is why such checking code will be slow, cumbersome, and thus prone to error.
Quote:
Originally Posted by exterminator
Another thing, there are various levels of exception guarantees that you can provide for your function. Even if you don't do anything and let the result of divide by zero be as it is, it should be responsibility of the caller to maintain the contract of the function, i.e. not passing a zero denominator.
Yes, understood. I already take all of these precautions. The callers don't invoke functions with improper input. The functions assert the input is proper for DEBUG mode, and attempts to deal with it properly in RELEASE mode. This thread is due to my concern of how to properly deal with this issue in RELEASE mode.
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by Paul McKenzie
... Compiled using Visual C++ 6.0, this does not throw an exception that your program can handle, because the CPU handled it and went on its merry way without you being aware anything wrong has happened. To have the exceptions handled by your app, you have to set the CPU's flags, either by control_fp() or setting the registers yourself using assembly language.
Yes, exactly. And I, on the other hand, want the exact opposite. I want the FPU to handle the exceptions, which is the default. I want it to return NaN upon invalid operations, and I want it continue on its merry way. My code will not need exception handling, and will handle these cases merely by testing the result to see if it is NaN. In short, I prefer 'error codes' style over 'exception handling' style of error checking.
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by Paul McKenzie
Depends on the C runtime library of the compiler. For all the Visual C++ compilers, the runtime library disables the floating point exceptions, and you must turn them on as the article describes (or you can turn them on by setting the FPU control word).
Ok, right. It doesn't matter what the default setting of the processor is (if there is such a thing); your runtime will initialize the control word to something, overwriting whatever it was before. Since, your runtime initialization is always invoked, you need to know what it initialized it to (or make sure you initialize it yourself).
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by MrViggy
Your code will only run on MIPS and ALPHA platforms if you compile it for them. You cannot compile a Windows EXE on an x86 platform, and expect it to run on a MIPS platform, IIRC.
Right. I am not familiar with those platforms, but it makes sense that they are not x86 compatible. _controlfp and _controlfp_s are "platform independent" so they should work identically for all such platforms. So, I should be ok if I must ensure the proper FPU control word via these functions.
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by spiritualfields
... If I had been dealing with this problem, I would have created an overflow on testing, and then been scratching my head over why an exception wasn't getting thrown. ...
I was surprised when I first realized this, too. But, then I recognized that this is a far better way of dealing with the problem. Sometimes infinities are ok, since they still can be used with < and >. The IEEE standard really is great. And I am glad that it is used by default. I just need to make sure that this is always the case, and that other applications or others thing I don't know about can't steal this assumption from me -- otherwise, I'll lose the robustness I am looking for.
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by Paul McKenzie
Well, if it were true, then anytime you run a Visual C++ app, you change the FPU globally. I highly doubt it, but you can easily test it by running two apps under the debugger and watch the registers. One program calls control_fp() with some wacky values, and see if the FPU control status word of the other program changes.
What does happen, and I've experienced it, is that any code that relies on third-party software, i.e. loading of drivers, then there is your risk of having the FPU control word change on you. The HP printer drivers from some time back were notorious for changing the state of the FPU control word whenever they were used.
I highly doubt this, as well. And, yes, you can test this just as you said. Good idea.
But, I think you've just solved the dilemma... The person posting the original story about how his application would crash due to the FP control word being changed stated that it was due to printer usage. I asked if his story's implication that the control word was global was true, and he replied and stated that he believes the printer usage may have been from his own application.
Thanks for all of your information, Paul. It is very valuable.
-
Re: Divide by 0 avoidance / handling
Perhaps a good question to ask, which I think I haven't, yet, is:
How do all of you avoid division by zero / overflows?
-
Re: Divide by 0 avoidance / handling
Sorry, I lost track of this thread.
Quote:
Originally Posted by JasonD
std::numeric_limits<T>::epsilon() returns the difference between 1 and the smallest value greater than 1 that the data type can represent. There are similar constants
defined in FLOAT.H:
Code:
#define FLT_EPSILON 1.192092896e-07F /* smallest such that 1.0+FLT_EPSILON != 1.0 */
#define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */
Yup! (the values are implementation dependent though)
Quote:
Originally Posted by JasonD
Firstly, your logic could be improved by only performing one check, instead of two: if (fabs(x) < epsilon) ... However, I don't follow your logic. I don't think it is correct.
Why don't you think it is correct? Can you prove it to me that it is incorrect? Can you show a sample code in your support?
Quote:
Originally Posted by JasonD
I realize you can multiply a value with these epsilon values to know the smallest absolute change that you can make to this original value, and get a different floating point representation (i.e. the value actually changes). These tolerances are VERY meaningful in this manner. But, to avoid an overflow, you must also be aware of the size of the numerator; not just the denominator (as I have already stated). This is why such checking code will be slow, cumbersome, and thus prone to error.
The problem is "Divide by 0" and what I suggested resolves that precisely. Now a calculation going out of bounds is a different thing altogether. That is a sign of logical code error. 0 denominator can be too but it is something that comes in directly as an argument so you can keep to have it as an argument validation. Going out of bounds in calculations happens because of 2 main reasons:
1. Logical error in code
2. Wrong data type choice (there are libs to handle very large numbers, you might try that)
Having said that, it is not impossible to even check out of bound condition in your code. Here is a sample:
Code:
template <typename T>
T bounds_checked_quotient_finder(T numerator, T denominator)
T temp = std::numeric_limits<T>::max()/numerator;
if (temp > denominator)
{
//it will surely go out of bound
throw out_of_bound_exception();
}
else
{
//check for divide by zero.. if it is then throw divide_by_zero_exception
//else perfectly safe to do the division
temp = numerator/denominator;
}
return temp;
}
(untested/uncompiled code sample)
But it is just too much for nothing. The two things that I mentioned above are the things that need to be taken care of.
-
Re: Divide by 0 avoidance / handling
Thanks for your post, again.
Quote:
Originally Posted by exterminator
Yup! (the values are implementation dependent though)
I don't follow what you mean by implementation dependent. If we deal with 32-bit and 64-bit IEEE floating point storage, these values should never change. Do you mean that these values will be different when running on hardware that doesn't use these two IEEE standards for float and double?
Quote:
Originally Posted by exterminator
Why don't you think it is correct? Can you prove it to me that it is incorrect? Can you show a sample code in your support?
I have two concerns:
#1. prevent divide by 0, and
#2. prevent overflow via division.
Since #1. divide by 0 can be prevented merely via:
if (x==0.0) { dont_divide; }
then I assume your solution was to my problem #2 (which is the whole point of this thread). Thus, I assume you are trying to arrive at a way to prevent division when it would cause overflow. And, you stated:
Quote:
Originally Posted by exterminator
...you should check the input if negative by adding std::numeric_limits<float>::epsilon() to see if it becomes positive and if input is positive by subtracting that value to see if it becomes negative. If it does then you can consider it to be 0 and restrict division...
Assuming double type for the moment, your logic is as follows (rounding epsilon to 2.22e-16 for ease of writing):
Code:
if (x<0.0)
{
if (x + 2.22e-16 > 0.0) dont_divide;
}
else
{
if (x - 2.22e-16 < 0.0) dont_divide;
}
So, you are just checking to see if the magnitude of x is less than the epsilon. Thus, the logic is the same as what follows:
Code:
if (fabs(x) < 2.22e-16) dont_divide;
But, and as I have already explained in my original post, and in my reply to your post, an overflow due to division is dependent on the numerator, as well! The minimum value you can divide by changes if the numerator changes. Thus, checking the denominator against an absolute value, without regard to the numerator, is insufficient. The value must be relative.
(I think this is clear, but, as you requested, here is one example that shows the above logic will not work. Given 1e-15, which the above code will not catch, the following results: 1e+309 / 1e-15 = 1e+324 = overflow.)
Quote:
Originally Posted by exterminator
The problem is "Divide by 0" and what I suggested resolves that precisely. Now a calculation going out of bounds is a different thing altogether.
Ok, wait... Now, it appears that your above code was an attempt to avoid division by 0 only, and not overflow. But, this is simply done like so:
if (x == 0.0) dont_divide;
I still don't see the use of the epsilon. Please explain, since I am not following your logic.
Quote:
Originally Posted by exterminator
That is a sign of logical code error. 0 denominator can be too but it is something that comes in directly as an argument so you can keep to have it as an argument validation. Going out of bounds in calculations happens because of 2 main reasons:
1. Logical error in code
2. Wrong data type choice (there are libs to handle very large numbers, you might try that)
Ok, again, exterminator, you have offered this extra knowledge in code safety / security. Which, I appreciate. But, as I have already said in my first reply to you, I am aware of this, and this is not the issue I am trying to solve. To make this absolutely clear: I have no intention of ever dividing by 0, or dividing by a number so small that it will overflow even a 32-bit float. My functions check all input, except in the most lowest level functions (that are called millions of times) in which their callers extensively check all parameters. All callers to all functions also check input before invoking a function. Furthermore, I use assert() statements in every imaginable place to catch problems, even small tolerance problems, the moment something goes slightly out of expected range. Now, this leaves me with one final issue to solve: What should I do when this code is in production on a user's home machine, and something completely unexpected will cause a division overflow / divide by 0? I am unwilling to refuse the checking of divide by 0 or division that causes overflow because I believe my code logic is correct. I don't trust my logic this much, and no one else should trust their own to this degree. Bugs happen. I have assertions everywhere just because I know my logic is not perfect. These are standard programming practices. These unexpected logic flaws can miss the unit testing and beta testing, and happen in the field. No matter how much you attempt to prevent this, you cannot be 100% sure that you can prevent them from occurring. I just don't trust the combination of my logic + compiler's logic + OS logic + hardware. All of these will never equate into 0 problems. I am well aware that the biggest issue is my own faulty logic. Some algorithms are very complex, and sometimes, you just don't know what may happen -- if even just in 1 in a billion chance. THUS, I assume there will be problems no matter what I do. And I want to deal with it when it happens. This is the method for the most robust code possible. I must assume that such divides will happen. This is the point of this thread: What do you do when the unexpected happens? How do you deal with this in a very quick way, since these tests will be performed in the production build on end users' machines, perhaps millions of times? (i.e. performance is critical)
Quote:
Originally Posted by exterminator
Having said that, it is not impossible to even check out of bound condition in your code. Here is a sample:
Code:
template <typename T>
T bounds_checked_quotient_finder(T numerator, T denominator)
T temp = std::numeric_limits<T>::max()/numerator;
if (temp > denominator)
{
//it will surely go out of bound
throw out_of_bound_exception();
}
else
{
//check for divide by zero.. if it is then throw divide_by_zero_exception
//else perfectly safe to do the division
temp = numerator/denominator;
}
return temp;
}
(untested/uncompiled code sample)
But it is just too much for nothing. The two things that I mentioned above are the things that need to be taken care of.
Well, yes and no...
Yes, the above is too much for what it solves, I agree. This is why I figure you can just let all operations go through, letting the FPU use NaNs in each operation, even AFTER the faulty one, and at the very end, I can merely do this:
if (_isnan(x)) { deal_with_error; }
No, what you imply is incorrect. The above two things DO have to be taken care of -- yes -- but they are not the ONLY things that needs to be taken care of. In my case, these two are already handled. I am now on step #3. Step #3 is what I explained in depth above. Step #3 is the reason for this thread. It is the next step to creating absolutely robust code.
I hope I have explained anything I left vague before...
Thanks for your time,
-
Re: Divide by 0 avoidance / handling
Does anyone else wish to share how they deal with / avoid division by zero and overflow due to division?
I'd love to hear about it.
-
Re: Divide by 0 avoidance / handling
Hey, Jason! :)
Got your PM. I have the subscriptions. I did not feel like replying because whatever I would be saying would be a repeatition of what I already said. [not to mention that I visit here only when there's nothing much in non-visual C++ forum/C#/Databases/ and of course chit chat :D].. Seriously? It's diwali time here in India.. :)
You are thinking too hard about it.
No one does anything exceptional about divisions anyway. Like I said, the causes of the problem are the 2 things I already mentioned.
Consider the case, where I am to apply Newton-Raphson technique to determine the yield to maturity of a bond given its price or for that matter am implementing any other numerical method.. what do I do? There would be a lot of arithmetic (division too!) involved. I am not going to call bounds_checked_quotient_finder() always.. doesn't make sense. What do I do, I do simple maths.. choosing the right datatypes and right techniques... Check for divide by zero that I mentioned using epsilon is the maximum I will do. And mind you - you cannot compare floating points for 0 by just using == with 0.0 - It could be a result of an operation or anything and the fact that floating point numbers cannot be represented precisely in binary.. I cannot do that. I "have to" use epsilon or a MACRO that defines the value.
Regarding your "something really unexpected" - I think you are asking about something more than the problems of overflow or divide by zero. You are talking about exceptions.. and that too not just application related exceptions but system exceptions as well.. But for that you have exception handling... Try searching for exception handling threads in non-Visual C++ forum... you will get many.
//Happy Diwali to all who celebrate :wave:
-
Re: Divide by 0 avoidance / handling
Hi exterminator, thanks for replying. I thought I lost you.
Quote:
Originally Posted by exterminator
I did not feel like replying because whatever I would be saying would be a repetition of what I already said.
Fair enough. However, I thought I brought forth some valid points that differed from your thoughts.
Quote:
Originally Posted by exterminator
You are thinking too hard about it.
I just want the most robust code possible, with simple error checking, and without sacrificing speed. I believe my proposed solution obtains all of these things.
Quote:
Originally Posted by exterminator
No one does anything exceptional about divisions anyway. Like I said, the causes of the problem are the 2 things I already mentioned.
That's my fear... that people don't do anything and just assume their logic / algorithms are flawless. I don't trust either. The most likely causes are the 2 things you mentioned, and I have already taken care of these, as I have said. Now, for the unlikely causes of bad divisions, I want to ensure my production code doesn't flop. Again, I want the most robust code possible.
Quote:
Originally Posted by exterminator
Consider the case, where I am to apply Newton-Raphson technique to determine the yield to maturity of a bond given its price or for that matter am implementing any other numerical method.. what do I do? There would be a lot of arithmetic (division too!) involved. I am not going to call bounds_checked_quotient_finder() always.. doesn't make sense.
Yes, you cannot call such a function before each division, you are correct. I am not implying that you should, in fact, I said from the start that this would slow and bloat the code. My proposed solution states you should perform only one much more simple check at the very end. It's faster, the code isn't complex, it needs only be called once, it's much more clean, and its robust.
The alternative is to not check at all, as you propose, and assume your logic / algorithms are perfect. But, the point of robust code is that it works in cases that were unexpected. In your example, I am sure you cannot possibly predict every resultant operation that Newton's method may cause. So, instead of assuming success, why not check the final result and have robust code?
Quote:
Originally Posted by exterminator
What do I do, I do simple maths.. choosing the right data types and right techniques...
Of course. As do I. But, even the right math can be faulty in some cases, due to strange boundary cases, precision errors, etc. You cannot prevent these cases with 100% certainty. Robust code assumes these cases may occur, and can handle them when they do. This is my goal.
Quote:
Originally Posted by exterminator
Check for divide by zero that I mentioned using epsilon is the maximum I will do. And mind you - you cannot compare floating points for 0 by just using == with 0.0 - It could be a result of an operation or anything and the fact that floating point numbers cannot be represented precisely in binary.. I cannot do that. I "have to" use epsilon or a MACRO that defines the value.
Ok, you are confusing two different things...
I understand that FP are not represented exactly in binary. I know you must use an epsilon to compare two FP numbers, as a result of inaccurate storage and accumulative error. But, your use of epsilon is incorrect. The epsilon has to be relative to the numbers being compared. Those epsilon constants are used to create the epsilon that you need, not to be used as-is. The are only useful in respect to the number 1.0, simply because this is how they are defined. You must account for the magnitude of your numbers, and the amount of accumulative error. (And use fabs() to be more efficient.)
The above epsilon talk is besides the point. To prevent infinity from occurring due to a division by 0, you only need check to see if the divisor is exactly 0. Dividing by something close to 0, but not 0, hardly ever returns infinity due to the limited precision of the FPU. If you are dealing with numbers far greater than the smallest magnitude FP (~1e-309), then your divisors will either be exactly 0.0, or they will be so large (but still close to 0, say 1e-20) that they will not cause infinity to occur. Epsilon is not required for a 'divide by 0' check.
To be more clear: You are speaking about checking to see if some arbitrary variable is 0, and yes, you need to use an epsilon for this, just as if you were comparing two FP values. I am speaking about preventing a division by 0, so I only need to check to see if divisor is exactly 0.
(Since there is great confusing here, I want to clarify that I am aware of algorithms in which you expect a 0 result, and due to FP inaccuracies, you will get something only close to 0 instead. In these cases, yes, you should see if the number is close to being 0, and change it to be 0. This is not what 'division by 0' is about.)
(Also, for those joining mid-thread, I do realize there is still the chance that a divisor is so small that when divided into the dividend that it causes overflow. The minimal divisor value to avoid such a case is dependent on the dividend's value. Such an 'epsilon' must be computed at runtime from the dividend, and cannot be determined by the aforementioned constants. This is not the issue I speaking about above, although it is the main concern raised in this thread.)
Quote:
Originally Posted by exterminator
Regarding your "something really unexpected" - I think you are asking about something more than the problems of overflow or divide by zero. You are talking about exceptions.. and that too not just application related exceptions but system exceptions as well.. But for that you have exception handling... Try searching for exception handling threads in non-Visual C++ forum... you will get many.
No, I am not speaking about exceptions. I am talking about FP overflow.
I am sorry, but I just really don't know where the break in our communication is occurring.
The "something really unexpected" is just a concrete example where you cannot assume that FP values are as expected. I chose it because it is one example that no one can argue against, because, when the hardware cannot be trusted to work, you have no idea what will happen. If you do not believe in such a crazy claim, please read this post by Raymond Chen on overclocking. Note that computers are being sold overclocked unbeknownst to customers:
The Old New Thing: There's an awful lot of overclocking out there
Yes, I admit, this is an extreme case. The much, much more likely case is that merely your logic / algorithm is faulty. And that is the reason we make robust code. If our logic never fails, and the algorithm never fails, and the compiler, the OS, and hardware never fails, then why make robust code at all? Why even bother?
-
Re: Divide by 0 avoidance / handling
Quote:
Originally Posted by gstercken
No, you can't assume that... By default, floating point exceptions are turned on. It depends on the implementation of the floating point library you use - and the VC++ standard library happens to turn them off.
/fp (Specify Floating-Point Behavior) can set FP exceptions to be on by default, rather than off, with /fp:except. Introduced in VC++ 2005. Not available for VC++ 2003.