由于"相同"的不同结果而感到困惑type cast,float to int

时间:2015-04-21 15:52:19

标签: 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;
}

有没有人能够洞察为什么“正确”是正确的,而“错误”是错误的?

顺便说一下,如果重要的话,我在Ubuntu 14.04 LTS上使用gcc 4.8.2。

2 个答案:

答案 0 :(得分:7)

您正在使用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;
}

输出:

     right = 65503
also right = 65503

答案 1 :(得分:4)

接受回答后

这不是doublefloat问题。它是一个二进制浮点数并转换为int/unsigned问题。

典型的float使用binary32表示法并未提供6550.3等值的精确表示。

float payloadInTons = 6550.3;
// payloadInTons has the exact value of `6550.2998046875`.

乘以下面的10.0,确保计算至少以double精度完成,精确结果为65502.998046875。然后将产品转换回floatdouble中的float值无法准确表示,因此会四舍五入为最佳float,其精确值为65503.0。然后tempVal根据需要转换right,其值为65503

float tempVal = payloadInTons * 10.0;
unsigned int right = tempVal;

乘以下面的10.0,确保计算至少以double精度完成,精确结果为65502.998046875,与以前一样。这一次,该值直接转换为unsigned rawPayloadN,其中包含值为65502的非期望值。这是因为截断值而非舍入值。

unsigned int rawPayloadN = payloadInTons * 10.0;

第一个“有效”因为转化为doublefloatunsigned。这涉及2次转换,通常是。在这种情况下,2个错误是正确的。


<强>解决方案

如果代码尝试float payloadInTons = 6550.29931640625;(下一个最小float个数字),则结果都是65502

将浮点值转换为某种整数类型的“正确”方法通常是舍入结果,然后执行类型转换。

float tempVal = payloadInTons * 10.0;
unsigned int right = roundf(tempVal);

注意:整个问题因FLT_EVAL_METHOD的值而变得复杂。如果用户的值不为零,则浮点计算可能会以高于预期的精度发生。

printf("FLT_EVAL_METHOD %d\n", (int) FLT_EVAL_METHOD);