1.6.9浮点错误


关于在计算机上处理媒介的问题,我们应该了解以下内容。 在比较浮点数时,由于浮点不精确,必须小心。 我们预计相同的两个浮点数可能略有不同。 例如,在数学上,我们希望归一化矢量的长度为1,但在计算机程序中,长度将只是大约1.此外,对于任何实数p,数学上1p = 1,但是当我们只 有1的数值近似,我们看到提升到p次幂的近似值增加了误差; 因此,数值误差也会累积。 以下简短的程序说明了这些想法:



#include <windows.h> // for XMVerifyCPUSupport
#include <DirectXMath.h>
#include <DirectXPackedVector.h>
#include <iostream>
using namespace std;
using namespace DirectX;
using namespace DirectX::PackedVector;


int main()
{
    cout.precision(8);


    // Check support for SSE2 (Pentium4, AMD K8, and above).
    if (!XMVerifyCPUSupport())
    {
        cout << "directx math not supported" << endl;
        return 0;
    }


    XMVECTOR u = XMVectorSet(1.0f, 1.0f, 1.0f, 0.0f);
    XMVECTOR n = XMVector3Normalize(u);


    float LU = XMVectorGetX(XMVector3Length(n));


    // Mathematically, the length should be 1.  Is it numerically?
    cout << LU << endl;
    if (LU == 1.0f)
        cout << "Length 1" << endl;
    else
        cout << "Length not 1" << endl;


    // Raising 1 to any power should still be 1.  Is it?
    float powLU = powf(LU, 1.0e6f);
    cout << "LU^(10^6) = " << powLU << endl;

}

1.6.9浮点错误

为了弥补浮点不精确性,我们测试两个浮点数是否近似相等。 我们通过定义一个Epsilon常量来做到这一点,这是一个非常小的值,我们用它作为“缓冲区”。如果它们的距离小于Epsilon,我们说两个值大致相等。 换句话说,Epsilon为我们提供了浮点不精确度的一些容差。 以下函数说明Epsilon如何用于测试两个浮点值是否相等:

const float Epsilon = 0.001f;
bool Equals(float lhs, float rhs)
{
// Is the distance between lhs and rhs less thanEPSILON?
return fabs(lhs - rhs) < Epsilon ? true : false;

}

当测试具有允许公差Epsilon参数的矢量的相等性时,DirectX Math库提供了XMVector3NearEqual函数:

// Returns
// abs(U.x – V.x) <= Epsilon.x &&
// abs(U.y – V.y) <= Epsilon.y &&
// abs(U.z – V.z) <= Epsilon.z
XMFINLINE bool XM_CALLCONV XMVector3NearEqual(
FXMVECTOR U,
FXMVECTOR V,
FXMVECTOR Epsilon);