Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect a double "overflow"?

Tags:

c++

I know that for big and small numbers double use scientific notation to store them. I wanted to create a function that given a string input could detect if that string is a double and it's not over or under double representation limit.

This following I tried to do does the job, but if i give a string input it returns true:

#import <limits>
#import <iostream>
#import <sstream>
#import <string>

bool isdouble(const string& str) {
    istringstream ss(str);
    double num;

    ss >> num;

    if (!ss.fail()) {
        return false;
    }
        
    return (num >= numeric_limits<double>::lowest() && 
            num <= numeric_limits<double>::max());
}

What can I do to make it work fine with string inputs too?

like image 987
Astra Avatar asked Sep 07 '26 06:09

Astra


1 Answers

Your check is wrong. num is a double. The maximum number a double can possibly store is numeric_limits <double> :: max(). Hence, num can never be larger than that value.

This

if (!ss.fail()){
    return false;

Is wrong, because it returns false when the extraction of a double from the stream does not fail. But the extraction fails when the string does not hold a double.

Your function can look like this:

#include <limits>
#include <iostream>
#include <sstream>
#include <string>

bool isdouble(const std::string& str) {
        
    std::istringstream ss(str);
    double num;
    return !!(ss >> num);
}

int main() {
    std::cout << std::numeric_limits<double>::max() << "\n";
    std::cout << isdouble("1e100") << "\n";
    std::cout << isdouble("1e310") << "\n";
}

Possible output:

1.79769e+308
1
0

When the stream is in an error state its conversion to bool yields false (remember that ss >> num yields a reference to ss). This conversion is explicit, but I used ! to trigger contextual conversion to bool, and !! to get the actual bool (I allowed myself a fancy way of writing static_cast<boo>(ss >> num)). Once extraction from the stream suceeds you need not check anymore if the value is in the range of double, because if it wasnt, the extraction would have failed.


PS: As suggested by TedLyngmo, to check if the whole string is nothing but a valid double you can change the above to:

return (ss >> num) && ss.peek() == std::char_traits<char>::eof();

This will make the function return false eg for "3.141 is not a number", because after extracting 3.141 as double there are still characters left in the stream.


PPS: As Eric Postpischil pointed out, the above "Hence, num can never be larger than that value." is not quite correct, because doubles can hold +Inf and -Inf. I don't know how to read them from a std::string, but if you want to exlcude them as "not in the range", they need to be taken into account in addition to the "can be extracted" check.

like image 133
463035818_is_not_a_number Avatar answered Sep 10 '26 05:09

463035818_is_not_a_number