don*_*edo 8 c++ gcc type-conversion
如果我首先将浮点计算的值赋给变量,然后使用隐式类型转换将其赋值给unsigned int,我得到一个答案.但是如果我将相同的计算直接分配给unsigned int,再次使用隐式类型转换,我得到一个不同的答案.
下面是我编译并运行以演示的示例代码:
#include <iostream>
int
main( int argc, char** argv )
{
float payloadInTons = 6550.3;
// Above, payloadInTons is given a value.
// Below, two different ways are used to type cast that same value,
// but the results do not match.
float tempVal = payloadInTons * 10.0;
unsigned int right = tempVal;
std::cout << " right = " << right << std::endl;
unsigned int rawPayloadN = payloadInTons * 10.0;
std::cout << " wrong = " << rawPayloadN << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
有没有人能够洞察为什么"正确"是正确的,而"错误"是错误的?
顺便说一句,我在Ubuntu 14.04 LTS上使用gcc 4.8.2,如果重要的话.
你正在使用double文字.有了正确的float文字,一切都很好.
int
main( int argc, char** argv )
{
float payloadInTons = 6550.3f;
float tempVal = payloadInTons * 10.0f;
unsigned int right = tempVal;
std::cout << " right = " << right << std::endl;
unsigned int rawPayloadN = payloadInTons * 10.0f;
std::cout << "also right = " << rawPayloadN << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
right = 65503
also right = 65503
Run Code Online (Sandbox Code Playgroud)
接受答案后
这不是double对抗float问题。它是一个二进制浮点数和转换int/unsigned问题。
典型的float使用binary32表示没有给出像 6550.3 这样的值的精确表示。
float payloadInTons = 6550.3;
// payloadInTons has the exact value of `6550.2998046875`.
Run Code Online (Sandbox Code Playgroud)
乘以10.0下面的 ,确保计算至少double以精确度完成,精确结果为65502.998046875。然后将产品转换回float. 该double值不能完全表示为float,因此四舍五入到float具有精确值的最佳值65503.0。然后根据需要进行tempVal转换right,值为65503。
float tempVal = payloadInTons * 10.0;
unsigned int right = tempVal;
Run Code Online (Sandbox Code Playgroud)
10.0下面乘以,确保计算至少double以精确度完成,结果65502.998046875与以前一样。这一次,该值被直接转换unsigned rawPayloadN为不想要的值为65502。这是因为值被截断而不是四舍五入。
unsigned int rawPayloadN = payloadInTons * 10.0;
Run Code Online (Sandbox Code Playgroud)
第一个“工作”,因为转换的是double要float来unsigned。这涉及 2 次转换,通常是不好的。在这种情况下,2 个错误变成了一个正确。
解决方案
如果代码尝试过float payloadInTons = 6550.29931640625;(下一个最小的float数字),两个结果都会是65502.
将浮点值转换为某种整数类型的“正确”方法通常是对结果进行四舍五入,然后执行类型转换。
float tempVal = payloadInTons * 10.0;
unsigned int right = roundf(tempVal);
Run Code Online (Sandbox Code Playgroud)
注意:整个问题由于 FLT_EVAL_METHOD. 如果用户的值不为零,浮点计算可能会以比预期更高的精度发生。
printf("FLT_EVAL_METHOD %d\n", (int) FLT_EVAL_METHOD);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
774 次 |
| 最近记录: |