是否有一种很好的方法可以从字符串中读取double
有关溢出的内容,即转换为"1e500" -> +inf
?
从我知道的字符串中读取的方法:
::std::stringstream
- 在溢出时返回垃圾; ::boost::lexical_cast
- 抛出bad_lixecal_cast,没有关于转换号码的有价值的信息::std::strtod
的cstdlib
- afaik它是唯一报告溢出的人(通过返回HUGE_VAL
并将errno
设置为ERANGE
),但使用这很安静不便特别需要一种方法可靠地将字符串转换为数字(double
),例如
"1e100" -> 1e100
"1e300" -> 1e300
"1e309" -> +inf // handling overflow as ieee-754 'inf'
编辑:
我实际上使用的是最后一种方法,这里是代码:
double stringToDouble(char const *str)
{
double result = ::std::strtod(str, 0);
if (ERANGE == errno)
{
if (HUGE_VAL == result)
{
result = INFINITY;
}
else if (-HUGE_VAL == result)
{
result = -INFINITY;
}
}
return result;
}
我很惊讶stringstream
没有很好地处理溢出。但它实际上返回了一些其他double
值(与正在读取的值无关),并且仅通过stream :: fail()表示报告。
但我仍然在寻找一些C ++ - 方式数字阅读。
答案 0 :(得分:1)
那么,你现在的C做事方式比我要建议的方式更有效率,但是因为你要求一个C ++方法,这里有一个通过定义一个类似操纵者的对象来保护你来自溢出:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <limits>
#include <algorithm>
using namespace std;
struct OverflowProtect
{
} limitdouble;
struct DoubleOverflowException : public std::exception
{
};
double stringToDouble(char const *str)
{
double result = ::std::strtod(str, 0);
if (ERANGE == errno)
{
if (HUGE_VAL == result)
{
throw DoubleOverflowException(); // throw whatever exception you want here
}
else if (-HUGE_VAL == result)
{
throw DoubleOverflowException(); // throw whatever exception you want here
}
}
return result;
}
istream & operator >> (istream & aIn, const OverflowProtect & aManip)
{
string number;
aIn >> number;
stringToDouble(number.c_str());
for_each(number.rbegin(), number.rend(), [&aIn](char c){aIn.putback(c);});
return aIn;
}
int _tmain(int argc, _TCHAR* argv[])
{
double nr;
try
{
cin >> limitdouble >> nr;
}
catch ( DoubleOverflowException & e )
{
// handle overflow exception thrown by limitdouble
e;
}
return 0;
}
不是最有效的方式,尤其是operator>>
实现,但毫无疑问是C ++,并且很有趣。
我确信可以做出改进,我只是在说明一个想法。