我写了一个iPhone-App,遇到了一个关于float和int之间的类型转换的问题。我在C中重写了代码,结果总是相同的,无论是在OS X(控制台和Xcode),Linux(控制台)还是Windows(Visual Studio)下编译的:
// Calculation of a page index depending on the amount of pages, its x-offset on the view
// and the total width of the view
#include <stdio.h>
int main()
{
int result = 0;
int pagesCnt = 23;
float offsetX = 2142.0f;
float width = 7038.0f;
offsetX = offsetX / width;
offsetX = (float)pagesCnt * offsetX;
result = (int)offsetX;
printf("%f (%d)\n", offsetX, result);
// The console should show "7.000000 (7)" now
// But actually I read "7.000000 (6)"
return 0;
}
当然,我们在这里失去了精确度。使用计算器x进行数学运算时,结果为7.00000000000008,而不是仅仅7.000000。
然而,尽管我理解C,但这应该不是问题,因为C意味着在将浮点数转换为整数时截断浮点数的后点位置。在这种情况下,这就是我想要的。
当使用double而不是float时,结果将如预期的那样,但我不需要这里的双精度,它应该没有任何区别。
我在这里弄错了吗?有没有我应该避免使用(int)转换为int的情况?为什么C递减结果呢?我应该总是使用双倍吗?
非常感谢!
编辑:我错误地表达了一些东西:当然,使用double而不是float时会有所不同。我的意思是,它不应该对(int)7.000000f或7.00000000000008产生影响。
编辑2:谢谢你,我现在理解我的错误。使用printf()而不定义浮点精度是错误的。当然,(int)6.99 ...到6是正确的。所以,在遇到这样的问题时,我将来会使用double。
答案 0 :(得分:4)
当我增加输出的精度时,我从您的程序收到的结果是6.99999952316284179688 (6)
,因此6
似乎是正确的。
答案 1 :(得分:1)
如果您将printf("%f (%d)\n", offsetX, result);
更改为printf("%.8f (%d)\n", offsetX, result);
,您会看到问题所在。进行更改后,输出为:
6.99999952 (6)
您可以通过舍入而不是转换为int
来更正此问题。也就是说,将result = (int)offsetX;
更改为result = roundf(offsetX);
。不要忘记#include <math.h>
。现在,输出是:
6.99999952 (7)
答案 2 :(得分:1)
在许多情况下,编译器不能自由地改变浮点运算的顺序,因为有限精度算法通常不是关联的。即,
(23 * 2142) / 7038 = 7.00000000000000000000
(2142 / 7038) * 23 = 6.99999999999999999979
这些不是单精度结果,但它表明双精度也无法解决您的问题。