我有一些代码块可以:
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/