C++ IsFloat 函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/447206/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:24:08  来源:igfitidea点击:

C++ IsFloat function

c++stringfloating-point

提问by AndyUK

Does anybody know of a convenient means of determining if a string value "qualifies" as a floating-point number?

有没有人知道一种方便的方法来确定字符串值是否“符合”作为浮点数的条件?

bool IsFloat( string MyString )
{
   ... etc ...

   return ... // true if float; false otherwise
}

回答by Bill the Lizard

If you can't use a Boost library function, you can write your own isFloat function like this.

如果您不能使用 Boost 库函数,您可以像这样编写自己的 isFloat 函数。

#include <string>
#include <sstream>

bool isFloat( string myString ) {
    std::istringstream iss(myString);
    float f;
    iss >> noskipws >> f; // noskipws considers leading whitespace invalid
    // Check the entire string was consumed and if either failbit or badbit is set
    return iss.eof() && !iss.fail(); 
}

回答by Adam Wright

You may like Boost's lexical_cast (see http://www.boost.org/doc/libs/1_37_0/libs/conversion/lexical_cast.htm).

您可能喜欢 Boost 的 lexical_cast(参见http://www.boost.org/doc/libs/1_37_0/libs/conversion/lexical_cast.htm)。

bool isFloat(const std::string &someString)
{
  using boost::lexical_cast;
  using boost::bad_lexical_cast; 

  try
  {
    boost::lexical_cast<float>(someString);
  }
  catch (bad_lexical_cast &)
  {
    return false;
  }

  return true;
}

You can use istream to avoid needing Boost, but frankly, Boost is just too good to leave out.

您可以使用 istream 来避免需要 Boost,但坦率地说,Boost 太好了,不能遗漏。

回答by Constantin

Inspired by this answerI modified the function to check if a string is a floating point number. It won't require boost & doesn't relies on stringstreams failbit - it's just plain parsing.

受此答案的启发,我修改了函数以检查字符串是否为浮点数。它不需要 boost 并且不依赖于 stringstreams failbit - 它只是简单的解析。

static bool isFloatNumber(const std::string& string){
    std::string::const_iterator it = string.begin();
    bool decimalPoint = false;
    int minSize = 0;
    if(string.size()>0 && (string[0] == '-' || string[0] == '+')){
      it++;
      minSize++;
    }
    while(it != string.end()){
      if(*it == '.'){
        if(!decimalPoint) decimalPoint = true;
        else break;
      }else if(!std::isdigit(*it) && ((*it!='f') || it+1 != string.end() || !decimalPoint)){
        break;
      }
      ++it;
    }
    return string.size()>minSize && it == string.end();
  }

I.e.

IE

1
2.
3.10000
4.2f
-5.3f
+6.2f

is recognized by this function correctly as float.

被此函数正确识别为浮点数。

1.0.0
2f
2.0f1

Are examples for not-valid floats. If you don't want to recognize floating point numbers in the format X.XXf, just remove the condition:

是无效浮点数的示例。如果您不想识别格式为 X.XXf 的浮点数,只需删除条件:

&& ((*it!='f') || it+1 != string.end() || !decimalPoint)

from line 9. And if you don't want to recognize numbers without '.' as float (i.e. not '1', only '1.', '1.0', '1.0f'...) then you can change the last line to:

从第 9 行开始。如果您不想识别没有 '.' 的数字。作为浮动(即不是'1',只有'1.'、'1.0'、'1.0f'...)那么你可以将最后一行更改为:

return string.size()>minSize && it == string.end() && decimalPoint;

However: There are plenty good reasons to use either boost's lexical_cast or the solution using stringstreams rather than this 'ugly function'. But It gives me more control over what kind of formats exactly I want to recognize as floating point numbers (i.e. maximum digits after decimal point...).

但是:有很多很好的理由使用 boost 的 lexical_cast 或使用 stringstreams 的解决方案而不是这个“丑陋的函数”。但它让我可以更好地控制我想要识别为浮点数的格式(即小数点后的最大位数......)。

回答by Yang Liu

I recently wrote a function to check whether a string is a number or not. This number can be an Integer or Float.

我最近写了一个函数来检查字符串是否是数字。这个数字可以是整数或浮点数。

You can twist my code and add some unit tests.

您可以扭曲我的代码并添加一些单元测试。

bool isNumber(string s)
{
    std::size_t char_pos(0);

    // skip the whilespaces
    char_pos = s.find_first_not_of(' ');
    if (char_pos == s.size()) return false;


    // check the significand
    if (s[char_pos] == '+' || s[char_pos] == '-') ++char_pos; // skip the sign if exist

    int n_nm, n_pt;
    for (n_nm = 0, n_pt = 0; std::isdigit(s[char_pos]) || s[char_pos] == '.'; ++char_pos) {
        s[char_pos] == '.' ? ++n_pt : ++n_nm;
    }
    if (n_pt>1 || n_nm<1) // no more than one point, at least one digit
        return false;

    // skip the trailing whitespaces
    while (s[char_pos] == ' ') {
        ++ char_pos;
    }

    return char_pos == s.size();  // must reach the ending 0 of the string
}


void UnitTest() {
    double num = std::stod("825FB7FC8CAF4342");
    string num_str = std::to_string(num);

    // Not number
    assert(!isNumber("1a23"));
    assert(!isNumber("3.7.1"));
    assert(!isNumber("825FB7FC8CAF4342"));
    assert(!isNumber(" + 23.24"));
    assert(!isNumber(" - 23.24"));

    // Is number
    assert(isNumber("123"));
    assert(isNumber("3.7"));
    assert(isNumber("+23.7"));
    assert(isNumber("  -423.789"));
    assert(isNumber("  -423.789    "));
}

回答by j_random_hacker

[EDIT: Fixed to forbid initial whitespace and trailing nonsense.]

[编辑:固定以禁止初始空格和尾随废话。]

#include <sstream>

bool isFloat(string s) {
    istringstream iss(s);
    float dummy;
    iss >> noskipws >> dummy;
    return iss && iss.eof();     // Result converted to bool
}

You could easily turn this into a function templated on a type Tinstead of float. This is essentially what Boost's lexical_castdoes.

您可以轻松地将其转换为基于类型T而不是float. 这基本上就是 Boost 的lexical_cast所做的。

回答by Greg Rogers

I'd imagine you'd want to run a regex match on the input string. I'd think it may be fairly complicated to test all the edge cases.

我想你想在输入字符串上运行正则表达式匹配。我认为测试所有边缘情况可能相当复杂。

This sitehas some good info on it. If you just want to skip to the end it says: ^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$

这个网站有一些很好的信息。如果您只想跳到最后,它会说:^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$

Which basically makes sense if you understand regex syntax.

如果您了解正则表达式语法,这基本上是有道理的。

回答by nedb

I always liked strtofsince it lets you specify an end pointer.

我一直很喜欢,strtof因为它可以让你指定一个结束指针。

bool isFloat(const std::string& str)
{
    char* ptr;
    strtof(str.c_str(), &ptr);
    return (*ptr) == '
bool isFloat(const std::string& str)
{
    if (str.empty())
        return false;

    char* ptr;
    strtof(str.c_str(), &ptr);
    return (*ptr) == '
size_t npos = word.find_first_not_of ( ".+-0123456789" );
if ( npos == std::string::npos ) {
   val = atof ( word.c_str() );
}
'; }
'; }

This works because the end pointer points to the character where the parse started to fail, therefore if it points to a nul-terminator, then the whole string was parsed as a float.

这是有效的,因为结束指针指向解析开始失败的字符,因此如果它指向空终止符,则整个字符串被解析为浮点数。

I'm surprised no one mentioned this method in the 10 years this question has been around, I suppose because it is more of a C-Styleway of doing it. However, it is still perfectly valid in C++, and more elegant than any stream solutions. Also, it works with "+inf" "-inf" and so on, and ignores leading whitespace.

我很惊讶在这个问题出现的 10 年里没有人提到这种方法,我想是因为它更像是一种C 风格的方法。但是,它在 C++ 中仍然完全有效,并且比任何流解决方案都更优雅。此外,它与“+inf”“-inf”等一起使用,并忽略前导空格。

EDIT

编辑

Don't be caught out by empty strings, otherwise the end pointer will be on the nul-termination (and therefore return true). The above code should be:

不要被空字符串捕获,否则结束指针将位于空终止处(因此返回 true)。上面的代码应该是:

bool isNum = true;
int st = 0;
while (word.at(st)==32) st++;    // leading spaces
ch = word.at(st);
if (ch == 43 || ch==45 ) st++;   // check +, -

for (int n = st; n < word.length(); n++) {
  char ch = word.at(n);
  if ( ch < 48 || ch > 57 || ch != 46 ) {
     isNum = false;
     break;   // not a num, early terminate
  } 
}

回答by ramakarl

The main issue with other responses is performance

其他响应的主要问题是性能

Often you don't need every corner case, for example maybe nan and -/+ inf, are not as important to cover as having speed. Maybe you don't need to handle 1.0E+03 notation. You just want a fastway to parse strings to numbers.

通常,您不需要每个角落情况,例如可能 nan 和 -/+ inf,都没有速度那么重要。也许您不需要处理 1.0E+03 表示法。您只需要一种将字符串解析为数字的快速方法。

Here is a simple, pure std::string way, that's not very fast:

这是一个简单的纯 std::string 方式,速度不是很快:

bool isFloat(const std::string& s) {
    try {
        std::stof(s);
        return true;
    } catch(...) {
        return false;
    }
}

This is slow because it is O(k*13), checking each char against 0 thur 9

这很慢,因为它是 O(k*13),根据 0 thur 9 检查每个字符

Here is a faster way:

这是一个更快的方法:

##代码##

This has the benefit of terminating early if anynon-numerical character is found, and it checks by range rather than every number digit (0-9). So the average compares is 3x per char, O(k*3), with early termination.

如果找到任何非数字字符,这样做的好处是可以提前终止,并且它会按范围而不是每个数字 (0-9) 进行检查。所以平均比较是每个字符 3x,O(k*3),提前终止。

Notice this technique is very similar to the actual one used in the stdlib 'atof' function: http://www.beedub.com/Sprite093/src/lib/c/stdlib/atof.c

请注意,此技术与 stdlib 'atof' 函数中使用的实际技术非常相似:http: //www.beedub.com/Sprite093/src/lib/c/stdlib/atof.c

回答by emlai

C++11 solution using std::stof:

C++11 解决方案使用std::stof

##代码##

回答by strager

You can use the methods described in How can I convert string to double in C++?, and instead of throwing a conversion_error, return false(indicating the string does not represent a float), and trueotherwise.

您可以使用如何在 C++ 中将字符串转换为双精度中描述的方法,而不是抛出 a conversion_error,返回false(表示字符串不代表 a float),true否则。