c++ - (float)(1.2345f * 6.7809) 是否比 1.2345f * 6.7809f 更准确?

标签 c++

我有一些代码块可以:

float total = <some float>;
double some_dbl = <some double>;

total *= some_dbl;

这引发了一个我想关闭的编译器警告,但我不喜欢关闭此类警告 - 相反,我宁愿根据需要显式转换类型。这让我开始思考......是 (float)(total * some_dbl)total * (float)some_dbl 更准确吗?它是特定于编译器还是特定于平台?

更好的代码示例(链接如下):

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

int main() {
    double d_total = 1.2345678;
    float f_total = (float)d_total;
    double some_dbl = 6.7809123;

    double actual = (d_total * some_dbl);
    float no_cast = (float)(f_total * some_dbl);
    float with_cast = (float)(f_total * (float)some_dbl);

    cout << "actual:               " << setprecision(25) << actual << endl;
    cout << "no_cast:              " << setprecision(25) << no_cast << endl;
    cout << "with_cast:            " << setprecision(25) << with_cast << endl;
    cout << "no_cast, nextafter:   " << setprecision(25) << nextafter(no_cast, 500.0f) << endl;

    cout << endl;

    cout << "Diff no_cast:   " << setprecision(25) << actual - no_cast << endl;
    cout << "Diff with_cast: " << setprecision(25) << with_cast - actual << endl;
    return 0;
}

编辑: 所以,我试了一下。通过我尝试过的示例,我确实很快找到了一个 total * (float)(some_dbl) 似乎准确的示例。我认为情况并非总是如此,而是运气好,或者编译器正在截断 double 以使其 float ,而不是四舍五入,这可能会导致更糟糕的结果。参见:http://ideone.com/sRXj1z

编辑 2: 我使用 std::nextafter 确认 (float)(total * some_dbl) 正在返回截断值,并更新了链接代码。这是非常令人惊讶的:如果在这种情况下编译器总是截断 double ,那么你可以说 (float)some_dbl <= some_dbl ,这意味着 with_cast <= no_cast 。然而,事实并非如此! with_cast 不仅大于 no_cast ,而且也更接近实际值,这有点令人惊讶,因为我们在乘法发生之前丢弃了信息。

最佳答案

这会根据所涉及的数字的大小而有所不同,因为 double不仅仅是更精确,还可以容纳大于 float 的数字.这是一个示例,将显示一个这样的实例:

double d = FLT_MAX * 2.0;
float f = 1.0f / FLT_MAX;

printf("%f\n", d * f);
printf("%f\n", (float)d * f);
printf("%f\n", (float)(d * f));

输出:

2.000000
inf
2.000000

发生这种情况是因为虽然 float显然可以保存计算的结果 -- 2.0 , 它不能保存 FLT_MAX * 2.0 的中间值

关于c++ - (float)(1.2345f * 6.7809) 是否比 1.2345f * 6.7809f 更准确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26729327/

相关文章:

c++ - Boost:boost::slot<>::~slot 崩溃的原因可能是什么?

c++ - 使用 GDB 调试 .out 对象,使用 cmake 编译

c++ - OpenGL 主循环绘制巨大的点 vector

c++ - 生成文件行 `test -f `

c++ - 弃用 header <codecvt> 替换

c++ - Boost 安装 - 从源代码简化构建

c++ - 我应该使用哪个数组/列表?

c++ - 使用 ncurses 在 C++ 中进行移动绑定(bind)

c++ - ptr_vector 迭代器不需要增量吗?

c++ - 将列出哪些设备