2016-01-23 114 views
0

不幸的是,我是一個新手程序員,但是相對有經驗的數學家。平滑循環週期性三角函數

我想開發遊戲,我想我已經幾乎掌握了OpenGL等一些基本線性代數數學。不幸的是,我還沒有技術知識來做圖形模擬。

作爲一項基本練習,我想嘗試模擬一個粒子在圓形路徑中的連續移動。我用簡單的參數化

double t=0; 
double x = cos(t), y = sin(t); 

我知道,雙有根據微軟的一系列1.7E +/- 308。那麼我的問題就是:「我怎樣才能確保粒子的最光滑的連續循環?」我認爲可能發生的問題是,如果程序運行時間足夠長,則t變得越來越大,我們將達到t將重置爲其最低值並且可能導致「跳轉」粒子的位置。

我想過這個,我想知道是否有必要從[1.7E-308,1.7E + 308)→[0,2π)創建一個映射t。這有助於防止任何位置「跳躍」?或者是否有這樣的問題,我不是預先設定的?我的計劃本來是以預定的速度增加t,我還沒有確定。但是我看到增加的速率決定了座標變化有多快,其中的座標變化有多快。

回答

1

你太擔心了。或者至少是錯誤的事情。太陽會變成一個紅色的巨人,吞噬地球,在你超過雙倍的最大值之前,增加小的增量。

稍微更嚴重的問題是t的絕對精度隨着幅度的增加而減小。這是基於這樣一個事實,即雙精度是相對於它的大小。即使這需要很長時間纔會成爲一個真正的問題,但在t超過雙倍範圍之前就會發生。

另一個相關且更真實的問題是,對於較大的輸入值,實現可能變得不太精確。您通常會在標準庫或硬件中找到的高質量實現有望減少參數,所以這應該不是什麼大問題。

所有這些都被說出來,避免了這些問題中的任何一個,儘管它們可能在現實中很遙遠,但是如此簡單以至於你不妨照顧它。您只需只要超過遞增之後2 * PI降低t值:

t += tInc; 
if (t > 2.0 * M_PI) 
{ 
    t -= 2.0 * M_PI; 
} 

這樣,該值將始終爲0到2 * pi之間留。

順便說一句:它應該是很少有你需要雙精度的任何與圖形相關的東西。除非您有非常不尋常的用例,否則使用float類型的變量和常量應該足夠。您將使用的圖形庫通常會以精確度爲float的精度運行,因此在您自己的代碼中使用double只會使用額外的內存,並導致大量類型轉換。

+0

我認爲使用M_PI來減少手動參數會導致計算出的正弦和餘弦值與sincos(i * angle_increment,&s,&c)相比不斷增加的相移,因爲M_PI只是近似數學π,但取決於用例,這可能無關緊要。 'sin(),cos(),sincos()'的非破壞實現將使用足夠精確的π內部逼近來避免相移問題。 – njuffa

+0

@njuffa你在比較什麼?無論您如何處理此問題,由於浮點精度有限,您都會遇到錯誤。正如我所解釋的那樣,如果「t」值越大,它本身就會失去精度。在某個時刻,當它的精確度大於增量時,它將完全停止增加。這似乎是一個更嚴重的問題。 –

+0

我完全同意,浮點表示的粒度隨着爭論最終導致問題的幅度越來越大而增加。由於提問者使用'double',它會在角度增量之前發生許多角度增量,特別是如果使用乘法來計算角度增量。我的觀點是,通過'M_PI'以上面建議的方式減少手動參數通常不適合使用來自C/C +標準數學庫的正確實現的三角函數,因爲這些函數包括更準確的內部參數減少。 – njuffa