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 :(得分:3)
问题是0.1
不能完全表示为二进制浮点数。每个float
值略低于您的预期,转换为int
向下舍入,给出的值比您预期的低一个。
您可以通过四舍五入到最接近的整数来获得预期值:
int wtf = std::round(offset);
答案 1 :(得分:1)
当i = 40.1f
偏移量为3.99993896
且不完全为4.对于您的示例,如果使用c ++ 11标准或者圆形不可用,则可以使用std::round(offset)
{{ 1}}
浮点数不能代表Universe中的所有值,在某些情况下,纸张上的数学在浮点数上是正确的,可能不是。
答案 2 :(得分:0)
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
base 10恰好等于0.001
base 2。