2014-04-25 121 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