Catch mathematical function exceptions
Suppose we want to use a mathematical function, such as the arcsin function asin (x). If the value of the variable element x is provided by the user or an intermediate result, when calling, you must determine whether the value range is reasonable. Is it full? | x | <= 1? That is
If (FABS (x) <= 1) y = Asin (X );
Else y =...
Logarithm functions can also be processed similarly. However, if you encounter a power functionPow (x, y)The problem is not that simple. After careful analysis, we will find that:
Y X |
Negative decimal |
Negative integer |
0 |
Integer |
Decimal |
Negative decimal |
Meaningless |
Meaningful |
Meaningful |
Meaningful |
Meaningless |
Negative integer |
Meaningless |
Meaningful |
Meaningful |
Meaningful |
Meaningless |
0 |
Meaningless |
Meaningless |
Meaningful |
Meaningful |
Meaningful |
Integer |
Meaningful |
Meaningful |
Meaningful |
Meaningful |
Meaningful |
Decimal |
Meaningful |
Meaningful |
Meaningful |
Meaningful |
Meaningful |
For example, POW (-1.2,-1.2) =-1. # ind. If programming is required, at least six if statements are required. Even so, there is also trouble: how can we determine whether the value of a double-type variable is an integer or a decimal?
To handle exceptions in mathematical function operations, VC ++ provides a function named _ Mather. Its prototype is in: int _ matherr (struct _ exception * handle T );
To use this function, you only need to define a function where the mathematical function is applied, for example, # include
# Include
Void main ()
{
Double X, Y, Z;
X =-1.23;
Y =-1;
Z = POW (x, y );
Printf ("% G \ n", Z );
Y =-1.1;
Z = POW (x, y );
Printf ("% G \ n", Z );
}
Int _ matherr (struct _ exception * handle T)
{
Char * errorstring [] = {"_ domain", "_ sing", "_ overflow", "_ ploss ",
"_ Tloss", "_ underflow "};
Printf ("error function name is % s \ n", failed T-> name );
Printf ("The varianbles arg1 = % G, arg2 = % G \ n", struct T-> arg1, struct T-> arg2 );
Printf ("the error type = % s \ n", errorstring [handle T-> type]);
Printf ("the error value = % G \ n", doesn t-> retval );
Counter T-> retval = 1234;
Printf ("after handling error value = % G \ n", doesn t-> retval );
Return 1;
}
Compile and run. The result is-0.813008.
Error Function Name Is pow
The varianbles arg1 =-1.23, arg2 =-1.1
The error type = _ sing
The error value =-1. # ind
After handling error value = 1234
1234
Press any key to continue
First act-the reciprocal of 1.23, second ~ The second row is the output of the _ matherr function, and the seventh row is the output of the main function.
Some people may say that the main function does not call the _ matherr function. Why does this happen? This is what the VC ++ compiler has done for us. It is very likely to set a jump in a mathematical function to implement Exception Handling. When the point function in the mathematical library detects an error, it calls this function. The following describes the _ matherr function:
1. Return Value: the type is integer. By convention, the 0 return value is used to mark an error. A non-0 value indicates success. If 0 is returned, the error message is displayed, and the error sequence number is correctly set. If a non-zero value is returned, no error message is displayed, and the error sequence number remains unchanged.
2. Parameter: pointer to a structure struct _ exception containing error information.
The _ exception structure contains the following data members:
Int type exception type;
Char * Name: name of the function with an error;
Double arg1, the first and second parameters of the arg2 function (if any;
The Return Value of the double retval function.
Note: The error types of mathematical functions are defined as follows:
_ Domain variable meta-defined domain error;
_ Sing element singular point error;
_ Overflow error;
_ The precision of the ploss is missing;
_ Loss of tloss precision;
_ Underflow overflow error. The result is too small.
The following is an example provided by msdn for your reference:
/* Matherr. c extends strates writing an error routine for math
* Functions. The error function must be:
* _ Matherr
*/
# Include
# Include
# Include
Void main ()
{
/* Do several math operations that cause errors. The _ matherr
* Routine handles _ domain errors, but lets the system handle
* Other errors normally.
*/
Printf ("log (-2.0) = % E \ n", log (-2.0 ));
Printf ("log10 (-5.0) = % E \ n", log10 (-5.0 ));
Printf ("log (0.0) = % E \ n", log (0.0 ));
}
/* Handle several math errors caused by passing a negative argument
* To log or log10 (_ domain errors). When this happens, _ matherr
* Returns the natural or base-10 logarithm of the absolute value
* Of the argument and suppresses the usual error message.
*/
Int _ matherr (struct _ exception * handle T)
{
/* Handle _ domain Errors for log or log10 .*/
If (struct T-> type = _ domain)
{
If (strcmp (random t-> name, "log") = 0)
{
Counter T-> retval = Log (-(counter T-> arg1 ));
Printf ("Special: using absolute value: % s: _ domain"
"Error \ n", doesn t-> name );
Return 1;
}
Else if (strcmp (partition T-> name, "log10") = 0)
{
Response T-> retval = log10 (-(Response T-> arg1 ));
Printf ("Special: using absolute value: % s: _ domain"
"Error \ n", doesn t-> name );
Return 1;
}
}
Else
{
Printf ("Normal :");
Return 0;/* Else use the default actions */
}
}
Output result
Special: using absolute value: Log: _ domain Error
Log (-2.0) = 6.931472e-001
Special: using absolute value: log10: _ domain Error
Log10 (-5.0) = 6.989700e-001
Normal: log (0.0) =-1. # inf00e + 000