acosf的奇怪实现

acosf的奇怪实现,c,visual-studio-2010,floating-point,language-lawyer,C,Visual Studio 2010,Floating Point,Language Lawyer,我遇到了一个奇怪的问题: 我在acosf中得到了浮点异常(我们显式地启用了它们,并使用/fp:strict) 我们有2个32位浮点向量,需要计算角度 float32 len1 = Vec_Len(vec1); float32 len2 = Vec_Len(vec2); float32 angle = acosf( (vec1.x * vec2.x + vec1.y * vec2.y)/(len1*len2) ); 非常直截了当。 发生的问题是无效的操作异常。 检查计算值发现,acosf调用中的

我遇到了一个奇怪的问题:

我在acosf中得到了浮点异常(我们显式地启用了它们,并使用/fp:strict)

我们有2个32位浮点向量,需要计算角度

float32 len1 = Vec_Len(vec1);
float32 len2 = Vec_Len(vec2);
float32 angle = acosf( (vec1.x * vec2.x + vec1.y * vec2.y)/(len1*len2) );
非常直截了当。 发生的问题是无效的操作异常。 检查计算值发现,
acosf
调用中的表达式的计算结果为
double
(请记住:在C中,浮点表达式总是升级为double)值略大于
1.0
(欢迎来到浮点数学世界)。 到目前为止还不错-但是四舍五入到float32精度的表达式正好是
1.0f
(我还检查了二进制表示)

那么,他妈的为什么会触发
acosf
这个异常呢?在传递参数时,表达式不应该被截断/舍入/什么都应该被截断

经过短暂思考:我在“Microsoft Visual Studio 10.0\VC\include\math.h”中找到了这个:

这是文件中的一个定义,但它似乎是活动的,因为我可以在预处理文件中看到它

这是‘合法’吗? 在我看来,这违反了“似乎”规则

这个定义(也在文件中)似乎更适合我

inline float acosf(_In_ float _X)
        {return ((float)acos((double)_X)); }

尝试
angle=(acosf)(…)。函数名周围的附加括号用于禁用宏扩展。。。更好的方法是:去掉浮动,然后在double中执行所有操作。去掉浮动不是一个选项,因为我们是故意使用它们的。我们的目标体系结构仅支持32位floats@pmg当然,将
acosf
放在括号中没有帮助,因为这是stdlib实现
acosf
的方式。将其放在括号中会导致编译器错误。请参阅:“…函数的任何宏定义都可以在本地被抑制…”。您的编译器不符合标准:(@pmg我不明白你的意思。stdlib必须实现一组已定义的函数。如果它将它们作为其他函数的宏别名来实现,只要它们的行为与指定的一样,就不应该有任何关系。当然,如果它们定义了它,并且你强制禁止该调用的宏替换-为什么这是编译器问题e、 我认为问题在于,宏没有强制将参数截断为浮点。比如
#define acosf(x)((float)acos((float)(x))
Try
angle=(acosf)(…);
。函数名周围的附加括号禁用宏扩展…甚至更好:去掉
float
并在
double
中执行所有操作。去掉float不是一个选项,因为我们是故意使用它们的。我们的目标体系结构只支持32位floats@pmg将
acosf
放在课程的括号中e没有帮助,因为这是stdlib实现
acosf
的方式。将其放在括号中会导致编译器错误。请参阅:“…函数的任何宏定义都可以在本地被抑制…”。您的编译器不符合标准:(@pmg我不明白你的意思。stdlib必须实现一组已定义的函数。如果它将它们作为其他函数的宏别名来实现,只要它们的行为与指定的一样,就不应该有任何关系。当然,如果它们定义了它,并且你强制禁止该调用的宏替换-为什么这是编译器问题e、 我认为问题在于,宏没有强制将参数截断为浮点。如
#define acosf(x)((float)acos((float)(x))
inline float acosf(_In_ float _X)
        {return ((float)acos((double)_X)); }