2

有没有一种从字符串中读取double溢出的好方法,即转换"1e500" -> +inf

我知道从字符串中读取的方法:

  • ::std::stringstream- 溢出时返回垃圾;
  • ::boost::lexical_cast- 抛出 bad_lixecal_cast,没有关于正在转换的数字的有价值信息
  • ::std::strtodfrom cstdlib- afaik 它是唯一一个报告溢出的(通过返回HUGE_VAL并设置errnoERANGE),但使用它很不方便

特别是我需要一种可靠地将字符串转换为数字(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++ 方式的数字阅读。

4

1 回答 1

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++,而且很有趣。我确信可以进行改进,我只是说明一个想法。

于 2012-09-14T09:51:18.380 回答