【问题标题】:Implicit type conversion in CC中的隐式类型转换
【发布时间】:2011-12-25 18:18:31
【问题描述】:

我在 wikipedia (http://en.wikipedia.org/wiki/Type_conversion#Implicit_type_conversion) 上偶然发现了以下示例。

#include <stdio.h>

int main()
{
    int i_value   = 16777217;
    float f_value = 16777217.0;
    printf("The integer is: %i\n", i_value); // 16777217
    printf("The float is:   %f\n", f_value); // 16777216.000000
    printf("Their equality: %i\n", i_value == f_value); // result is 0
}

他们的解释:“这种奇怪的行为是由于 i_value 与 f_value 比较时隐式转换为浮动造成的;这种转换失去了精度,使得被比较的值不同。”

这不是错的吗?如果将 i_value 强制转换为浮点数,那么两者的精度损失将相同,并且它们将相等。 所以 i_value 必须强制转换为 double。

【问题讨论】:

  • 使用 g++ (GCC 4.6.2) 我得到 1 表示平等。
  • @Kerrek:还有我。在 VS 中,我得到 0。
  • @OliCharlesworth:我很好奇将文字更改为f 或将类型更改为double——在所有情况下我都会得到1...
  • 您可能正在使用 x64 系统,它不使用 10 字节扩展,而是使用通常的双精度。您还可以使用 -mfpmath=sse -msse 在 32 位 cpu 上观察这一点。

标签: c floating-point type-conversion


【解决方案1】:

我认为 32 位 IEEE 浮点可以容纳的最大整数值是 1048576,它小于上面的数字。所以,浮点值肯定不会正好是 16777217。

我不确定的部分是编译器如何在两种不同类型的数字(即浮点数和整数)之间进行比较。我可以想到三种不同的方法:

1) 将两个值都转换为“float”(这应该使值相同,所以这可能不是编译器所做的)

2) 将两个值都转换为“int”(这可能会或可能不会将它们显示为相同...转换为 int 通常会截断,因此如果浮点值为 16777216.99999,则转换为“int”会截断)

3) 将两个值都转换为“double”。我的猜测是编译器会这样做。如果这是编译器所做的,那么这两个值肯定会不同。 double 可以准确地保存 16777217,也可以准确地表示 16777217.0 转换为的浮点值(不完全是 16777217.0)。

【讨论】:

    【解决方案2】:

    不,在相等运算符的情况下,“通常的算术转换”发生,开始:

    • 首先,如果任一操作数对应的实类型为long double,则转换另一操作数,不改变类型 域,对应真实类型为long double的类型。
    • 否则,如果任一操作数对应的实类型为double,则转换另一操作数,不改变类型 域,对应真实类型为double的类型。
    • 否则,如果任一操作数对应的实类型为float,则转换另一操作数,不改变类型 域,对应真实类型为float的类型。

    最后一种情况在这里适用:i_value 转换为 float

    您可以从比较中看到奇怪的结果,尽管这是因为对通常的算术转换的警告:

    浮动操作数的值和浮动结果的值 表达式可以以更高的精度和范围来表示 类型要求的;类型不会因此而改变。

    这是正在发生的事情:转换后的i_value 的类型仍然是float,但是在这个表达式中,您的编译器正在利用这个纬度并以比float 更高的精度来表示它。这是编译 387 兼容浮点时的典型编译器行为,因为编译器将临时值留在浮点堆栈上,该堆栈以 80 位扩展精度格式存储浮点数。

    如果您的编译器是gcc,您可以通过提供-ffloat-store 命令行选项来禁用此附加精度。

    【讨论】:

    • 在 x64 gcc 上使用显式 cvtsi2ssl 指令将整数转换为浮点数。然而,在 x86 上,这正是发生的情况,更高的精度实际上甚至大于两倍。
    • @konrad.kruczynski:是的,您可以通过提供-mfpmath=sse 选项(这也需要-msse 或暗示该选项的选项)在x86 上获得相同的结果。
    【解决方案3】:

    这里有一些很好的答案。您必须非常小心地在各种整数和各种浮点表示之间进行转换。

    我通常不测试浮点数的相等性,尤其是如果其中一个来自整数类型的隐式或显式转换。我在一个充满几何计算的应用程序上工作。我们尽可能使用标准化整数(通过强制我们在输入数据中接受的最大精度)。对于必须使用浮点的情况,如果需要比较,我们将对差值应用绝对值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      相关资源
      最近更新 更多