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.)