2

doubleオーバーフローに関して文字列から読み取る良い方法、つまり convert はあり"1e500" -> +infますか?

私が知っている文字列から読み取る方法:

  • ::std::stringstream- オーバーフロー時にガベージを返します。
  • ::boost::lexical_cast- 変換中の数値に関する価値のある情報なしで bad_lixecal_cast をスローしました
  • ::std::strtodからcstdlib- オーバーフローについて報告するのは唯一のものです(に戻っ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++の方法で数値を読み取る方法を探しています。

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 に答える