gpt4 book ai didi

c++ - 奇怪的,float类型的参数在windows中传入函数

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:56:25 24 4
gpt4 key购买 nike

有一段代码把我搞糊涂了,是在windows下运行的!这是代码:

#define point_float2uint(x) *((unsigned int *)&x)


float divide_1000(float y)
{
float v = y / 1000.0f;
return v;
}

float divide_1000(int y)
{
float v = float(y) / 1000.0f;
return v;
}


void float_test(void)
{
int num[5] = {67975500, 67251500, 67540620, 69435500, 70171500};
for (int i = 0; i < 5; ++i)
{
int a = num[i];
float af_f = divide_1000(float(a));
float af_i = divide_1000((a));
printf("src num:%d, af_f:%f, %x, af_i:%f, %x\n", num[i], af_f, point_float2uint(af_f), af_i, point_float2uint(af_i));
}
}

这是由 vs2005 编译的输出:

src num:67975500,  af_f:67975.507813, 4784c3c1, af_i:67975.500000, 4784c3c0
src num:67251500, af_f:67251.507813, 478359c1, af_i:67251.500000, 478359c0
src num:67540620, af_f:67540.625000, 4783ea50, af_i:67540.617188, 4783ea4f
src num:69435500, af_f:69435.507813, 47879dc1, af_i:69435.500000, 47879dc0
src num:70171500, af_f:70171.507813, 47890dc1, af_i:70171.500000, 47890dc0

问题是:为什么我使用“divide_1000”,在windows中得到不同的结果?这不是我想要的!而且我发现并不是所有的整数结果都不同,但有些就像上面的代码一样。

这是输出,由 debian 中的 gcc4.4.5 编译:

src num:67975500,  af_f:67975.507812, 4784c3c1, af_i:67975.507812, 4784c3c1
src num:67251500, af_f:67251.507812, 478359c1, af_i:67251.507812, 478359c1
src num:67540620, af_f:67540.625000, 4783ea50, af_i:67540.625000, 4783ea50
src num:69435500, af_f:69435.507812, 47879dc1, af_i:69435.507812, 47879dc1
src num:70171500, af_f:70171.507812, 47890dc1, af_i:70171.507812, 47890dc1

我在使用不同的函数“divide_1000”时得到了相同的结果。这就是我想要的。

最佳答案

这里涉及很多影响结果的代码生成设置。当使用“经典”FPU 指令进行浮点计算时,在默认浮点模型(即“精确”模型)下的非优化代码中可以观察到您报告的差异。

编译器按字面意思翻译第一次调用:原始整数值首先转换为 float - 4 字节浮点值 - 存储在内存中(作为函数参数)。此转换将值四舍五入为 +6.7975504e+7,这已经不精确了。随后,float 值从第一个函数内的内存中读取,并用于进一步的计算。

第二次调用传递一个int值给函数,该值直接加载到高精度FPU寄存器中,用于进一步的计算。即使您在第二个函数中指定了从 intfloat 的显式转换,编译器还是决定忽略您的请求。此值永远不会按字面意思转换为 float,这意味着上述精度损失永远不会发生。

这就是造成您观察到的差异的原因。

如果您将第二个函数重写为

float divide_1000(int y)
{
float fy = y;
float v = fy / 1000.0f;
return v;
}

即添加一个将 float 值保存到内存中指定位置的附加步骤,编译器将在未优化的代码中执行该步骤。这将导致结果变得相同。

同样,上述内容适用于未经优化编译的代码,此时编译器通常会尝试非常接近地(但并不总是准确地)翻译所有语句。在优化代码中,编译器消除了到 float 的“不必要”中间转换以及两种情况下所有“不必要”的中间内存存储,从而产生相同的结果。

您可能还想尝试其他浮点模型(即“严格”和“快速”)以了解它如何影响结果。这些浮点模型专门用于处理您观察到的问题。

如果您更改编译器的代码生成设置并使其使用 SSE 指令进行浮点运算,结果也可能会改变(在我的实验中,当使用 SSE2 指令集而不是 FPU 指令时,差异消失)。

关于c++ - 奇怪的,float类型的参数在windows中传入函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17441731/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com