从float到int的C(C ++,Objective-C)类型转换导致递减的int

时间:2011-11-22 16:10:14

标签: c casting floating-point int

我写了一个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。

3 个答案:

答案 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

这些不是单精度结果,但它表明双精度也无法解决您的问题。