2014-04-25 70 views
0

我发现3D Vector规范化存在问题。它似乎只发生在一些特定的数字。每次我调用标准化函数时,Vector都会发生变化。3D矢量规范化问题

示例代码:

Vector3 v1(-0.965090453265, -0.210381150246, 0.156014174223); 

std::cout.precision(15); 
v1.normalize(); 
std::cout << v1 << std::endl; 
v1.normalize(); 
std::cout << v1 << std::endl; 
v1.normalize(); 
std::cout << v1 << std::endl; 
v1.normalize(); 
std::cout << v1 << std::endl; 

输出:

-0.965090334415436 -0.210381120443344 0.156014159321785 
-0.965090453624725 -0.210381150245667 0.156014174222946 
-0.965090334415436 -0.210381120443344 0.156014159321785 
-0.965090453624725 -0.210381150245667 0.156014174222946 

规格化功能:

void Vector3::normalize() 
{ 
    if (length() == 0) 
     return; 

    Vector3 x = *this; 
    float sqr = x.x * x.x + x.y * x.y + x.z * x.z; 
    *this = x * (1.0f/std::sqrt(sqr)); 
} 

这是否是float精度的问题,或者我的代码有问题?如何避免这个问题?

回答

3

编辑:只是想出了为什么我不能再现问题。

如果我改变x /= len在我的代码下面x *= ((t) 1.)/len然后我结束了你给什么为floats,即超越了前六位数字(你不应该反正信任float)不一致的答案:

-0.965090334415436 -0.210381120443344 0.156014159321785 
-0.965090453624725 -0.210381150245667 0.156014174222946 
-0.965090334415436 -0.210381120443344 0.156014159321785 
-0.965090453624725 -0.210381150245667 0.156014174222946 
-0.965090334415436 -0.210381120443344 0.156014159321785 

正如预期的那样,doubles仍然正确达15位数:

-0.965090340387771 -0.210381125639766 0.156014155975542 
-0.965090340387771 -0.210381125639766 0.156014155975542 
-0.965090340387771 -0.210381125639766 0.156014155975542 
-0.965090340387771 -0.210381125639766 0.156014155975542 
-0.965090340387771 -0.210381125639766 0.156014155975542 

不过,float重sult始终与前六位数字保持一致。

原贴:

这似乎是“只是一个浮点精度的问题”,因为单精度浮点只给你最多6-9 decimal digits of precision。我已经编写了代码来检查这一点,而且我的结果看起来不像您的结果差。

#include <iostream> 
#include <cmath> 

template <typename t> 
class Vector3 
{ 

public: 
    t x; 
    t y; 
    t z; 

    Vector3 (t x, t y, t z) : 
     x (x), 
     y (y), 
     z (z) 
    {} 

    void normalize() 
    { 
     t len = std::sqrt(x * x + y * y + z * z); 

     if (len != 0.) 
     { 
      x /= len; 
      y /= len; 
      z /= len; 
     } 
    } 

    void println() 
    { 
     std::cout << x << " " << y << " " << z << std::endl; 
    } 

}; 

int main(int argc, char ** argv) 
{ 
    std::cout.precision(15); 

    Vector3<float> v(-0.965090453265, -0.210381150246, 0.156014174223); 

    for (int i = 0; i < 5; ++i) 
    { 
     v.normalize(); 
     v.println(); 
    } 

    return 0; 

} 

输出:

-0.965090334415436 -0.210381120443344 0.156014159321785 
-0.965090394020081 -0.210381135344505 0.156014174222946 
-0.965090394020081 -0.210381135344505 0.156014174222946 
-0.965090394020081 -0.210381135344505 0.156014174222946 
-0.965090394020081 -0.210381135344505 0.156014174222946 

更改Vector3<float>Vector3<double>给出了一致的结果高达15位数:

-0.965090340387771 -0.210381125639766 0.156014155975542 
-0.965090340387771 -0.210381125639766 0.156014155975542 
-0.965090340387771 -0.210381125639766 0.156014155975542 
-0.965090340387771 -0.210381125639766 0.156014155975542 
-0.965090340387771 -0.210381125639766 0.156014155975542 

注意,即使float结果停止变化,数字是不实际纠正超出前七。

+0

我已将我的标准化功能更改为您的标准化功能,而且对于我目前的需求,它似乎还可以。非常感谢你的帮助!最好的祝福。 – Tom