What is wrong with my exception handling here? - c++

I am trying to write a custom function that can raise any number 'a' to the power 'b' and i'm only interested in getting the real portion of my answer. I have written my own function to handle, but it still fails when a is negative. Can any tell me how I go about fixing this, please?
#include <exception>
...
double power(double a, double b) {
double output;
try {output = pow(a,b);}
catch (std::domain_error) { //even if I use catch(...) I still get a NaN.
if (b==0.0) output = 1.0;
if (a==0.0) output = 0.0;
if (b<0.0) {
b=-1.0*b;
try {output = 1.0/pow(a,b);}
catch (std::domain_error){
a = -1.0*a;
output = -1.0/pow(a,b);
}}
else {
a=-1.0*a;
output = -1.0*pow(a,b);}
}
return output;
}
Many thanks for the replies. I have read the responses and made the following code.
double power(double a, double b) {
double output;
output = pow(a,b);
if (output != output) {
if (b==0.0) output = 1.0;
if (a==0.0) output = 0.0;
else if (b<0.0) {
b=-1.0*b;
output = 1.0/pow(a,b);
if (output != output) {
a = -1.0*a;
output = -1.0/pow(a,b);
}}
else {
a=-1.0*a;
output = -1.0*pow(a,b);}
}
if (output >= DBL_MAX) output = DBL_MAX;
if (output <= -DBL_MAX) output =-DBL_MAX;
if ((output >= -DBL_MIN) && (output <= DBL_MIN)) output = 0.0;
return output;
}
My only remaining question is how does c++ handle 1.0/inf? I hope that it will be caught by
if ((output >= -DBL_MIN) && (output <= DBL_MIN)) output = 0.0;

The floating point arithmetic handling doesn't throw std::exceptions: it just return special values that represent the exception:
In partucular, for the std::pow function, the documetation says:
...
Domain error occurs if base is 0 and exp is less than or equal to ​0​.
NAN is returned in that case
...
It doesn't say that std::domain_error is thrown, but that NAN is returned to represent thaat anomaly.
Since no throw is made, there is nothing to catch.
For your purposes, don't use exceptions: since you know what kind of input you want to handle, just pre-filter it.

Math functions do not throw exceptions - they set special exception flags (more about it in Floating-point environment, there is even example).
To check whether your pow function failed, either check whether the return value is NAN, or use one of the floating exception functions to do it (assuming you set it properly).

Related

More general test for same order of magnitude than comparing floor(log10(abs(n)))

I am implementing an optimization algorithm and have diferent heuristics for cases where no or largely different lower and upper bounds for the solution are known or not.
To check, my first approach would be simply taking
if(abs(floor(log10(abs(LBD))) - floor(log10(abs(UBD)))) < 1 )
{ //(<1 e.g. for 6, 13)
//Bounds are sufficiently close for the serious stuff
}
else {
//We need some more black magic
}
But this requires previous checks to be gerneralized to NAN, ±INFINITY.
Also, in the case where LBD is negative and UBD positive we can't assume that the above check alone assures us that they are anywhere close to being of equal order of magnitude.
Is there a dedicated approach to this or am I stuck with this hackery?
Thanks to geza I realized that thw whole thing can be done without the log10:
A working solution is posted below, and a MWE including the log variant posted on ideone.
template <typename T> double sgn(T val) {
return double((T(0) < val) - (val < T(0)))/(val == val);
}
bool closeEnough(double LBD, double UBD, uint maxOrderDiff = 1, uint cutoffOrder = 1) {
double sgn_LBD = sgn(LBD);
double sgn_UBD = sgn(UBD);
double cutoff = pow(10, cutoffOrder);
double maxDiff = pow(10, maxOrderDiff);
if(sgn_LBD == sgn_UBD) {
if(abs(LBD)<cutoff && abs(UBD)<cutoff) return true;
return LBD<UBD && abs(UBD)<abs(LBD)*maxDiff;
}
else if(sgn_UBD > 0) {
return -LBD<cutoff && UBD<cutoff;
}
// if none of the above matches LBD >= UBD or any of the two is NAN
}
As a bonus it can take cutoffs, so if both bounds lie within [-10^cutoffOrder,+10^cutoffOrder] they are considered to be close enough!
The pow computation might also be unecessary, but at least in my case this check is not in a critical code section.
If it would be, I suppose you could just hard code the cutoff and maxDiff.

Arithmetic Error When Converting String to Double

I'm writing a function to convert a user provided string into a double. It works quite well for certain values, but fails for others. For example
string_to_double("123.45") = 123.45
string_to_double(12345) = 12345
but
string_to_double(123.4567) = 123.457
I'm fairly certain that this is some kind of round off error, but I'm not using approximations nor am I using very small or large values. My question is two-fold why am I getting these strange results and how can I change my code to get more accurate results? I'm also doing this as a personal challenge, so suggestions to use methods such as std::stod are not helpful. I believe the problem occurs in the second for-loop, but I felt it was wise to include the entire method because if I missed something it isn't that much extra code to read.
My Code
template <class T>
double numerical_descriptive_measures<T>::string_to_double(std::string user_input)
{
double numeric_value = 0;//Stores numeric value of string. Return value.
int user_input_size = user_input.size();
int power = 0;
/*This loop is for the characteristic portion of the input
once this loop finishes, we know what to multiply the
characterstic portion by(e.g. 1234 = 1*10^3 + 2*10^2 + 3*10^1 + 4)
*/
for(int i = 0;i < user_input_size;i++)
{
if(user_input[i] == '.')
break;
else
power++;
}
/*This loop is for the mantissa. If this portion is zero,
the loop doesn't execute because i will be greater than
user_input_size.*/
for(int i = 0;i < user_input_size;i++)
{
if(user_input[i] != '.')
{
numeric_value += ((double)user_input[i] - 48.0)*pow(10,power-i-1);
}
else
{
double power = -1.0;
for(int j = i+1;j < user_input_size;j++)
{
numeric_value += ((double)user_input[j] - 48.0)*pow(10.0,power);
power = power-1.0;
}
break;
}
}
return numeric_value;
}
The problem is not that you are producing the wrong floating point value, the problem is that you are printing it with insufficient precision:
std::cout<<data<<std::endl
This will only print about six digits of precision. You can use std::setprecision or other methods to print more.
Your code is not producing an incorrect value for "123.4567" but it will produce incorrect values in general. For example, string_to_double("0.0012") produces (on Visual Studio 2015)
0.0012000000000000001117161918529063768801279366016387939453125
but the correct answer is
0.00119999999999999989487575735580549007863737642765045166015625
(You would have to print them to 17 significant digits to tell the difference.)
The problem is that you can't use floating-point to convert to floating-point -- it does not have enough precision in general.
(I've written a lot about this on my site; for example, see http://www.exploringbinary.com/quick-and-dirty-decimal-to-floating-point-conversion/ and http://www.exploringbinary.com/decimal-to-floating-point-needs-arbitrary-precision/ .)

Return error code as double

I wonder if I can return error code as double in the following way in C:
double getValue()
{
double ret = 0;
if (error1)
{
return -1;
}
if (error2)
{
return -2;
}
return ret = ....;
}
int main(void)
{
double val = getValue();
if (-1 == val)
{
printf("getValue: error1\n")
return -1;
}
else if (-2 == val)
{
printf("getValue: error2\n");
return -2;
}
......
return 0;
}
so when the return value is >= 0 then it is correct value which can be used for calculations. When value is less than zero error occurred.
Will I get the floating-point-comparison problem when I compare return value with -1 or -2 ?
Flag values are a bad idea. Flag values that are floating point are doubly so, even if double precision.
If you are using IEEE double precision floating point values, the values -1 and -2 are exactly representable as doubles, and comparison is well defined. No "magic error" will slip in if you merely copy the double around or only read the value. In fact, on a system with conventional 2s complement 32 bit ints, every int can be represented exactly as a IEEE double precision floating point value.
Now, transformations you think wouldn't matter like x /3. * 3. will ruin the identity, so the code is very fragile: fragile both because flag values are fragile, and because floating point equivalence is often fragile in practice.
In C++, there are a myriad of ways to do this that are less fragile.
enum error_code {a,b,c};
boost::variant<double, error_code> getValue();
is a tagged union that can hold either a double or an error_code. There is a std::expected proposal you can look at which is a tagged union with a "bias" towards the first value being the only valid one (sort of a cross between std::experimental::optional and boost::variant).
Both of these result in the value being returned in a type-safe way, where an error is a different type of value than the non-error return type.
Alternative solutions include returning the error code separately (as the return value, or taking a pointer-to-error-code as a parameter (what I call ICU style)). The double could be set to some innocuous value in that case (say, NaN) rather than left uninitialized.
double getValue( error_code* e );
or
error_code getValue( double* out );
where enum error_code { a = -1, b = -2 } is an enumeration of the error codes.
#LightnessRacesinOrbit beat me to it, but having typed it I post it anyway.
You can do it by taking the value to be set as a pointer argument, and returning a status. That way, no values of *ret are barred.
int getValue(double *ret)
{
*ret = ...;
if (error1)
return -1;
if (error2)
return -2;
return 0;
}
Then the calling code can be such as
double myval;
int err;
if ((err = getValue(&myval)) == 0)
printf ("getValue() returned %f\n", myval);
else
printf ("getValue() returned error %d\n", err);
Yes, you could get floating-point errors.
So consider using exceptions instead, or perhaps return an int error code and populate a double "out parameter" on success:
int getValue(double& ret)
{
if (error1)
return -1;
if (error2)
return -2;
ret = ....;
return 0;
}
Doing that is not necessary and makes error handling difficult, you should create an enum where you can add or remove error codes as needed, and also you don't really need to remeber what -1 is or what does -2 mean, just give each error a descriptive name, and do this
enum ErrorCodes {NoError, Error1, Error2, ... , ErrorN};
enum ErrorCodes getValue(double *value)
{
if (error1)
return Error1;
if (error2)
return Error2;
.
.
.
if (errorN)
return ErrorN;
*value = resultOfCalculation;
return NoError;
}
then
enum ErrorCode code;
double value;
code = getValue(&value);
switch (code)
{
case NoError:
/* use value here */
break;
case Error1:
/* handle error 1 */
break;
/* and so on */
}
I think this is a lot better and elegant, because you can apply it anytime you want to have robust error checking, no matter what type the target value is, this would work exactly the same for a struct or a double or an int array.

Returning void from method to prevent execution

I am attempting to exit a method which returns void after checking a condition (I realize this would be easier if I threw an exception, but I'm trying to avoid that for this project). I have the code below, which should return out of the if statement, if I am interpreting it correctly, but the entire method is still executing. Is there a problem in the code somewhere (I can post more if needed), or is there a better way to write this without exception handling?
void Rational::divide(Rational b) {
if (b.numerator == 0) {
cout << "Cannot divide by zero." << endl;
return;
} else if (b.numerator != 0) {
numerator = numerator * b.denominator;
denominator = denominator * b.numerator;
reduce();
}
}
EDIT: I've updated the code to reflect some suggestions; just to clarify, the if statement itself is executing correctly (if b is zero, I get the error message) - once the error message is printed, the remainder of the method continues to run.
EDIT 2: Updated with else if revision.
And that is what you are doing. You probably want to do something like this in your ifstatement: if((double)b.denominator == 0.f).
You should also be careful when comparing with floats or double due to the way they are represented in memory. It will almost never be exactly zero, so you should compare with an epsilon.

c++ Receiving "-1.#IND" from output?

Pretty simple problem here:
When I test the wrong data input I give an error message but -1.#IND comes up after it?
for instance I type a negative where there should be a positive and I get "wrong input dummy-1.#IND"
#include "Header.h"
void error_rep(){
cout<<"Wrong input dummy";
}
double ctok(double c){
double j = c *273.15;
if (j >= -273.15){
return j;
}
else
error_rep();
}
int main(){
double c = 0;
cin >> c;
double k = ctok(c);
cout<<k<<endl;
keep_window_open();
}
What does this mean? and why is it coming up? How do I get rid of it?
What does this mean?
It's Microsoftese for "not a number". It means that k is not a valid floating-point number.
and why is it coming up?
When your range test fails, you don't return a value. This gives undefined behaviour; in practice, it's likely to be equivalent to returning an uninitalised value, which is likely to be garbage. Your compiler should warn you about this, if you have suitable warnings enabled.
How do i get rid of it?
I'd report the error by throwing an exception; then nothing can attempt to use the invalid return value if the function fails. Alternatively, you could return a type with a testable "invalid" state, such as boost::optional<double> or std::pair<double, bool>, and test it before use.
By the way, if that's supposed to be converting degrees Celsius to Kelvin, then you want to add 273.15, not multiply by it; and compare with zero after the conversion (or with 273.15 before converting, if you prefer).
A good compiler with all warning turns on, will have say that an execution path doesn't have a return ...,
double ctok(double c){
double j = c *273.15;
if (j >= -273.15){
return j;
}
else {
error_rep();
///here
throw ;//somthing
}
}
and try-catch exception around ctok call
-1.#IND means that the double value is "negative indefinate NaN". Basically the value stored can't be represented as a number in a double.
See http://blogs.msdn.com/b/oldnewthing/archive/2013/02/21/10395734.aspx