繁体   English   中英

从float到int的奇怪转换

[英]Strange conversion from float to int

for(float i = 40; i <= 42; i+=0.1f)
{
    float offset = (i-40) * 10 * sizeof(float);
    int wtf = offset;
    printf("%.1f =?= %d\n", offset, wtf);
    fseek(fin, offset, SEEK_SET);
    fread(&tf, sizeof(float), 1, fin);
    //printf("%.1f %.4f\n", i, tf);
}

输出:

0.0 =?= 0 4.0 =?= 3 8.0 =?= 7 12.0 =?= 11 16.0 =?= 15 20.0 =?= 19 24.0 =?= 23 28.0 =?= 27 32.0 =?= 31 36.0 =?= 35 40.0 =?= 39 44.0 =?= 43 48.0 =?= 47 52.0 =?= 51 56.0 =?= 55 60.0 =?= 59 64.0 =?= 63 68.0 =?= 67 72.0 =?= 71 76.0 =?= 75 80.0 =?= 79

我不明白这个,你能帮帮我吗?

问题是0.1不能完全表示为二进制浮点数。 每个float值都比您预期的要小一些,转换为int向下舍入,给出比您预期的值小一的值。

您可以通过四舍五入到最接近的整数来获得预期值:

int wtf = std::round(offset);

i = 40.1f偏移量将是3.99993896 ,它不完全是4.对于您的示例,如果使用c ++ 11标准或者如果舍入不可用,则可以使用std::round(offset) std::floor(offset + 0.5f);

浮点不能代表宇宙中的所有值,并且在某些情况下,纸张上的数学在浮点上是正确的,它可能不是。

在碱2中表示的0.1是

0.0001100110011001100110011001100110011...

分数中的0011无限重复,正如3在1/3 = 0.3333333 ...基数10中所做的那样。由于实际浮点值只能保持有限数量的数字,因此近似中必然存在误差。

唯一可以用基数2中有限位数表示的小数是那些有理数,其分母是2的整数。例如,用0.125f(= 1/8)代替0.1f

for(float i = 40; i <= 42; i+=0.125f)
{
    float offset = (i-40) * 10 * sizeof(float);
    int wtf = offset;
    printf("%.1f =?= %d\n", offset, wtf);
}

导致没有截断错误的值:

0.0 =?= 0
5.0 =?= 5
10.0 =?= 10
15.0 =?= 15
20.0 =?= 20
25.0 =?= 25
30.0 =?= 30
35.0 =?= 35
40.0 =?= 40
45.0 =?= 45
50.0 =?= 50
55.0 =?= 55
60.0 =?= 60
65.0 =?= 65
70.0 =?= 70
75.0 =?= 75
80.0 =?= 80

这是因为0.125碱基10精确等于0.001碱基2。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM