从字符串中读取溢出双倍作为'inf'的安全方法
Safe way to read overflowed double as 'inf' from string
有没有一种很好的方法可以从溢出的字符串中读取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++路数字读数。
好吧,你目前的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++式的,而且很有趣。我相信可以做出改进,我只是在说明一个想法。
相关文章:
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- C++从另一个类访问公共静态向量的正确方法是什么
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 没有为自己的结构调用列表推回方法
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 在类定义之后定义一个私有方法
- 枚举环境变量的惯用C++14/C++17方法
- 从字符串中读取溢出双倍作为'inf'的安全方法