【问题标题】:c++ float to bool conversionc++ float to bool
【发布时间】:2009-12-28 14:05:17
【问题描述】:

我正在查看一些第 3 方代码,但不确定其中一行在做什么。我无法发布确切的代码,但大致如下:

bool function(float x)
{
float f = doCalculation(x);
return x > 0 ? f : std::numeric_limits<float>::infinity();
}

这显然会引发编译器关于转换 float->bool 的警告,但实际行为会是什么? Visual C++ 如何将浮点数转换为布尔值?至少我应该能够取代那个讨厌的无穷大......

【问题讨论】:

  • 对我来说这看起来像是糟糕的代码。为什么要计算x &lt;= 0.0?为什么要麻烦写出无穷大而不是 1.0 的表达式,因为它们都转换为true?如果x &gt; 0.0f == 0.0 而不是abs(f) &lt; epsilon,为什么从x 计算一些东西并返回false,因为浮点相等(在floatbool 的转换中)是不确定的?我认为你那里有一些糟糕的代码。
  • 无法发布“确切”代码?函数(x)的“确切”名称是什么?
  • 它有什么不同?由于许可证限制,我无法发布代码,这足以等同于。
  • 因为函数名通常可以洞察程序员想要 function() 做什么——这是每个人都在猜测的。

标签: c++ visual-c++


【解决方案1】:

我认为这是一个错误。该函数应该返回一个浮点数。这在我看来是合乎逻辑的。

float 到 bool 的转换与 float != 0 相同。但是,由于精度,严格比较两个浮点并不总是如您所愿。

【讨论】:

  • 不是很有帮助。这是在一个工作的 3rd 方库中,我没有时间跟踪调用函数并弄清楚这一切......我只想知道浮点转换规则是什么,尤其是对于无穷大。
  • infinity 转换为 true,因为它不是零,但是这闻起来很像错字。
  • 怎么没用?他回答了您的问题:“将 float 转换为 bool 与 float != 0 相同”。无穷大等于零吗?如果不是,浮点数将转换为 true。
  • 我想说你没有时间不去追捕几个来电者,看看那里发生了什么。这显然是一个错误(尽管显然它现在没有造成任何麻烦)。如果你需要理解,你需要弄清楚调用者的想法,理解它的意思。
【解决方案2】:

如果 == 0.0f,浮点数将转换为 false,但请注意精度!否则它将被转换为true——如果它不是exacly 0.0f,它也将是true! Infinity 也将转换为true。正如 David Thornley 提到的,您的示例是非常糟糕的代码。

【讨论】:

    【解决方案3】:

    我认为使用 isnan() 会更好。

    isnan() 如果 f 不是数字,则返回 true。但它会返回真,例如0.0 ...

    #include <cmath>
    bool function(float x)
    {
        float f = doCalculation(x);
        return isnan(f) ? false : true;
    }
    

    如前所述,不会捕获 f 为 0.0 或非常接近的情况。

    如果你需要这个,你可以检查:

    bool near0 = std::abs(f) > std::numeric_limits<float>::epsilon();
    

    编辑:这里是一个改进的例子,包括一个测试驱动程序:

    #include <cmath>
    
    #include <limits>
    #include <iostream>
    #include <vector>
    
    // using namespace std;
    bool fn(float f) {
        if (isnan(f)) return false; // it is not-a-number
        return std::abs(f) > std::numeric_limits<float>::epsilon();
    }
    
    // testdriver
    int main(void) {
        std::vector<float> t;
        t.push_back(0.0);
        t.push_back(0.1);   
        t.push_back(-0.1);
        t.push_back( 0.0 + std::numeric_limits<float>::epsilon());  
        t.push_back( 0.0 - std::numeric_limits<float>::epsilon());
        t.push_back( 0.0 - 2*std::numeric_limits<float>::epsilon());
        t.push_back( 0.0 + 2*std::numeric_limits<float>::epsilon());
        t.push_back( 1.0 * std::numeric_limits<float>::epsilon());      
        t.push_back(-0.1 * std::numeric_limits<float>::epsilon());
        t.push_back( 0.1 * std::numeric_limits<float>::epsilon());
        for (unsigned int i=0; i<t.size(); i++) {
            std::cout << "fn(" << t[i] << ") returned " << fn(t[i]) << std::endl;
        }   
    }
    

    测试结果:

    fn(0) 返回 0 fn(0.1) 返回 1 fn(-0.1) 返回 1 fn(1.19209e-07) 返回 0 fn(-1.19209e-07) 返回 0 fn(-2.38419e-07) 返回 1 fn(2.38419e-07) 返回 1 fn(1.19209e-07) 返回 0 fn(-1.19209e-08) 返回 0 fn(1.19209e-08) 返回 0

    【讨论】:

      【解决方案4】:

      我通常会这样做

      return x != 0;
      

      【讨论】:

        【解决方案5】:

        假设 DoCalculation(x) 对于 x 的非正值返回 infinity() 那么对于 x 的正值 function(x) 对于 DoCalculation() 的非零值返回 true,否则返回 false。所以 function(x) 是确定 DoCalculation(x) 是否为零。我会将 function(x) 重命名为 IsDoCalculationNonzero(x)。

        【讨论】:

          【解决方案6】:

          这看起来很简单。请记住,布尔识别的唯一状态是零或非零。所以这段代码:

          return x > 0 ? f : std::numeric_limits<float>::infinity();
          

          评估如下:

          如果 x > 0:返回 f。如果 f == 0.0F 那么它将返回 false。 否则它将返回true。正如其他人所提到的,精度问题可能会给出错误的结果,但如果它有效,那么我会说不是......

          如果 x http://msdn.microsoft.com/en-us/library/85084kd6.aspx)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-03-22
            • 2010-10-30
            相关资源
            最近更新 更多