Float angle != angle什么时候为true?

栏目: IT技术 · 发布时间: 5年前

内容简介:[TOC]看到一段代码,顿时就呆了这样写的用意到底是啥呢?

[TOC]

看到一段代码,顿时就呆了

if (angle != angle)
    {
        return XMQuaternionIdentity();
    }

这样写的用意到底是啥呢?

源代码

代码很好理解,就是求两个向量的四元数表示的旋转角度

DirectX::XMVECTOR SimStarMan::QuaternionFromToRotation(const XMVECTOR& from, const XMVECTOR& to)
{
    XMVECTOR quatRet;
    XMVECTOR axis, fromN, toN;
    float angle;
    fromN = XMVector3Normalize(from);
    toN = XMVector3Normalize(to);
    const XMVECTOR epsilon = XMLoadFloat3(&XMFLOAT3(0.00001f, 0.00001f, 0.00001f));

    if (XMVector3NearEqual(fromN, toN, epsilon))
    {
        return XMQuaternionIdentity();
    }
    axis = XMVector3Cross(fromN, toN);
    axis = XMVector3Normalize(axis);
    angle = acosf(XMVectorGetX(XMVector3Dot(fromN, toN)));
    if (angle != angle)
    {
        return XMQuaternionIdentity();
    }
    quatRet = XMQuaternionRotationAxis(axis, angle);
    quatRet = XMQuaternionNormalize(quatRet);
    return quatRet;
}

探究

NAN

参考[2]中解释了,说IEEE标准规定,NaN和任何数比较都是false,所以只有当angle为NaN的时候, angle != angle才为true

float a = acos(2);
cout << "a = " << a << endl;    // a = nan
cout << (a != a) << endl;         // 1

向量可能有问题

比如某个向量是无限长,正如 XMVector3Normalize 文档提到的一样[3]

For a vector of length 0, this function returns a zero vector. For a vector with infinite length, it returns a vector of QNaN.

acosf会出现Nan的情况

如果输入范围有问题,那么结果就会出现NaN,第二条提到了[4]

If no errors occur, the arc cosine of arg (arccos(arg)) in the range [0 ; π], is returned.

If a domain error occurs, an implementation-defined value is returned (NaN where supported).

If a range error occurs due to underflow, the correct result (after rounding) is returned.

如何写更优雅?

参考[2]中有个评论是这么回答的:

This answer should be updated since std::isnan is now part of the C++11 standard and support has spread out. std::isnan was implemented in Visual Studio starting with Visual Studio 2013.

所以,上面的写法是不是写成下面这样,会更加清晰明了:

// old
angle ! = angle
// new
std::isnan(angle)

至此,这个问题算是清楚了,那么NaN到底是如何定义的呢?

NaN定义

参考[5][6]

IEEE 754 floating point numbers can represent positive or negative infinity, and NaN (not a number).

小结:

  • NaN在运算中得结果始终都是NaN,不像infinity有可能算出来一个正常值,比如 4/∞ = 0
  • NaN的浮点数IEEE表示是一个范围,节码都是1,所以尾数表示的范围都是NaN
Positive infinity is represented by the bit pattern X'7F80 0000'.
Negative infinity is represented by the bit pattern X'FF80 0000'.
A signaling NaN (NANS) is represented by any bit pattern between X'7F80 0001' and X'7FBF FFFF' or between X'FF80 0001' and X'FFBF FFFF'.
A quiet NaN (NANQ) is represented by any bit pattern between X'7FC0 0000' and X'7FFF FFFF' or between X'FFC0 0000' and X'FFFF FFFF'.

     31
     |
     | 30    23 22                    0
     | |      | |                     |
-----+-+------+-+---------------------+
qnan 0 11111111 10000000000000000000000
snan 0 11111111 01000000000000000000000
 inf 0 11111111 00000000000000000000000
-inf 1 11111111 00000000000000000000000
-----+-+------+-+---------------------+
     | |      | |                     |
     | +------+ +---------------------+
     |    |               |
     |    v               v
     | exponent        fraction
     |
     v
     sign

参考

[1] When is a float variable not equal to itself

[2] Checking if a double (or float) is NaN in C++

[3] XMVector3Normalize

[4] acos, acosf, acosl

[5] Infinity and NaNs

[6] 20.5.2 Infinity and NaN

[7] IEEE User’s Guide [8] What is difference between quiet NaN and signaling NaN?


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

算法之道

算法之道

邹恒明 / 机械工业出版社 / 2010-2 / 39.00元

《算法之道》追求的目标是算法背后的逻辑,是一本启示书,而不是一本包罗万象的算法大全。因此,《算法之道》甄选了那些最能够展现算法思想、战略和精华,并能够有效训练算法思维的内容。《算法之道》将算法的讨论分为五大部分:算法基础篇、算法设计篇、算法分析篇、经典算法篇、难解与无解篇。每一个部分分别讨论算法的一大方面:基础、设计、分析、经典和难解问题。 《算法之道》既可以作为大学本科或研究生的算法教材或......一起来看看 《算法之道》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具