内容简介:[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++
[7] IEEE User’s Guide [8] What is difference between quiet NaN and signaling NaN?
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 是时候谈谈JavaScript面向对象了!(我们什么时候更需要它)
- LWN:写文件的时候不希望写入一半的时候掉电丢失,怎么办?
- .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
- 什么时候要重写equals
- InnoDB数据页什么时候合并
- 放弃 OpenStack?恐怕还不到时候
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
人人时代(经典版)
[美] 克莱•舍基(Clay Shirky) / 胡泳、沈满琳 / 浙江人民出版社 / 2015-6 / 54.90元
[内容简介] 一而再,再而三出现的公众事件,绝不仅是来自草根的随兴狂欢,而是在昭示着一种变革未来的力量之崛起!基于爱、正义、共同的喜好和经历,人和人可以超越传统社会的种种限制,灵活而有效地采用即时通信、移动电话、网络日志和维基百科等新的社会性工具联结起来,一起分享、合作乃至展开集体行动。人人时代已经到来。 微软、诺基亚、宝洁、BBC、乐高、美国海军最推崇的咨询顾问,“互联网革命最伟大的......一起来看看 《人人时代(经典版)》 这本书的介绍吧!