【问题标题】:How do I perform a narrowing conversion from double to float safely?如何安全地执行从 double 到 float 的缩小转换?
【发布时间】:2022-11-16 04:34:37
【问题描述】:

当双精度缩小为浮点数时,我收到一些 -Wnarrowing 转换错误。我怎样才能以明确定义的方式做到这一点?最好使用模板中的选项,我可以切换行为,从抛出异常到限制到最接近的值,或简单的截断。我正在查看 gsl::narrow 演员表,但它似乎只是在幕后执行静态演员表和后续比较:Understanding gsl::narrow implementation。我想要更健壮的东西,因为根据 What are all the common undefined behaviours that a C++ programmer should know about? static_cast&lt;&gt; 是 UB 如果目标类型中的值不可表示。我也很喜欢这个实现,但它也依赖于 static_cast&lt;&gt;Can a static_cast<float> from double, assigned to double be optimized away? 我不想为此使用 boost。还有其他选择吗?如果这在 c++03 中有效是最好的,但是 c++0x(experimental c++11) 也是可以接受的……或者如果真的需要的话 11……

因为有人问,这里有一个简单的玩具示例:

#include <iostream>

float doubleToFloat(double num) {
    return static_cast<float>(num);
}

int main( int, char**){
    double source = 1; // assume 1 could be any valid double value
    try{
        float dest = doubleToFloat(source);
        std::cout << "Source: (" << source << ") Dest: (" << dest << ")" << std::endl;
    }
    catch( std::exception& e )
    {
        std::cout << "Got exception error: " << e.what() << std::endl;
    }
}

我的主要兴趣是向 doubleToFloat(...) 添加错误处理和安全性,如果需要,可以使用各种自定义异常。

【问题讨论】:

  • 请将您的代码放在问题中。
  • @Casey 添加了一个例子
  • double 不能表示为 float 当且仅当其绝对值大于 FLT_MAX
  • @n.m.是的,但我认为这还不够,是吗?你不需要考虑精度损失吗?和负数,但我觉得一些 abs() 调用使一切都变成正数可能会解决这个问题......
  • @n.m.在连续的 float 值之间有很多 double 值。 Demo。他们不算“不可代表”吗?

标签: c++ c++11 casting type-conversion c++03


【解决方案1】:

这取决于你所说的“安全”是什么意思。在大多数情况下,精度很可能会下降。你想检测是否发生这种情况?断言,还是只知道它并通知用户?

一种可能的解决方案是将 double 静态转换为 float,然后再转换为 double,然后比较之前和之后。平等是不可能的,但你可以断言精度损失在你的容忍范围内。

float doubleToFloat(double a_in, bool& ar_withinSpec, double a_tolerance) 
{
    auto reducedPrecision = static_cast<float>(a_in);
    auto roundTrip = static_cast<double>(reducedPrecision);
    ar_withinSpec = (roundTrip < a_tolerance);
    return reducedPrecision;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多