2013-08-07 115 views
2

好的,我有一個我的Trig類,用於存儲值的靜態表,以便更快地執行我的程序中的sin,cos和tan函數。是否有任何意見和/或速度的改進,可以對我目前的方法?由於之前的答案,我已經感覺C++更勝任了。可能的代碼速度優化?

Trig.h

#pragma once 
#include <math.h> 

class Trig 
{ 
private: 
    struct Table 
    { 
     static const int multiple = 10; // Accurately stores values to 1/10 of a degree 
     double sin[360*multiple]; 
     Table(); 
    }; 
    static const Table table; 
    static void shrinkRange(double*); // Shrinks degrees to range 0-359 for proper array indexing 
public: 
    static double sin(double); 
    static double cos(double); 
    static double tan(double); 
}; 

Trig.cpp

#include "Trig.h" 

Trig::Table::Table() // table constructor 
{ 
    double const PI = 3.14159265358979323; 
    double const degToRad = PI/180.0; 
    double const incr = 1.0/multiple; 
    int index = 0; 
    for (double angle = 0; index != 360*table.multiple; angle += incr) 
     Table::sin[index++] = _INC_MATH::sin(angle*degToRad); 
} 

Trig::Table const Trig::table; // initialize static table member 

void Trig::shrinkRange(double* degrees) 
{ 
    if (*degrees >= 360) 
     *degrees -= 360*((int)*degrees/360); 
    if (*degrees < 0) 
     *degrees += 360*(-(int)*degrees/360 + 1); 
} 

double Trig::sin(double degrees) 
{ 
    shrinkRange(&degrees); 
    degrees *= table.multiple; 
    return Trig::table.sin[(int)(degrees+0.5)]; 
} 

double Trig::cos(double degrees) 
{ 
    return Trig::sin(degrees + 90); 
} 

double Trig::tan(double degrees) 
{ 
    return Trig::sin(degrees)/Trig::cos(degrees); 
} 
+2

這不是Java。它是'Trig :: createTable'。 –

+4

這是基本的C++語法。我建議獲得[一本好書](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)。 (嘗試'Trig :: createTable()') –

+0

編輯現有的封閉式題外話題是毫無意義的,因爲它與主題等原始問題沒有關係。因此,您可能想要問一個新問題。 –

回答

0
Trig::createTable(); 
double x = Trig::COS_Table[120]; 
+2

歡迎使用堆棧溢出。請儘快閱讀[關於]頁面。請注意,在回答問題時,請注意您的答案在語法上是正確的。還需要添加一點解釋。修正後(通過在'120後面加'';''),你的代碼是準確的,但你應該提及改變('::'而不是'.'兩次,並加入'()')並簡要解釋爲什麼他們是必要的。 –

0

爲了獲得你需要使用::

Trig::COS_TABLE 

而非靜態

但是,只包含靜態的類在C++中有點奇怪。

+0

不是。特徵被廣泛用於定製模板。 (當然,在這種情況下,我更期望課堂上有更多的東西,而且他只是簡單地剪掉那些不會導致他問題的部分,否則,是的:這不會是慣用的。可能不會使成員靜態,但聲明一個靜態實例,並使用cosntructor來進行初始化。) –

+0

@JamesKanze當然你是對的,它只是在這裏聞起來像一個Javaism。 – doctorlove

+0

可能值得一提的是::是一個運算符,稱爲範圍解析運算符。 –

2

C++不是Java。在這種情況下,因爲沒有類對象,所以不能調用函數或訪問類中的成員; 你可以簡單地通過指定範圍內訪問靜態成員:

Trig::createTable(); 
Trig::COS_TABLE[120]; 

而且(但這是真正的在Java中也一樣),就可以自動 通過使用動態 初始化確保正確的初始化。如果你真的想保持目前的 結構,您可以添加類似:

bool initted = (Trig::createTable(), true); 

在命名空間內的任何地方。更地道是定義 對象類型包含兩個表,一個構造函數 其初始化它們,並聲明這一個靜態實例:

class Trig 
{ 
public: 
    struct Tables 
    { 
     double sin[360]; 
     double cos[360]; 
     Tables(); 
    }; 
    static Tables const tables; 
    // ... 
}; 

Trig::Tables const Trig::tables; 

Trig::Tables::Tables() 
{ 
    double rad = PI/180.0; 
    for (int angle = 0; angle != 360; ++ angle) { 
     sin[angle] = std::sin(angle * rad); 
     cos[angle] = std::cos(angle * rad); 
    } 
} 

無需顯式調用Trig::createTable;編譯器 負責照顧你。

(類似的技術可在Java中。出於某種原因, 它們不經常使用,其中如上述非常慣用 C++。)

0

靜態變量需要使用namespcae操作者::不像.要被訪問用於Java。

因此,調用方法createTable(),而無需創建一個對象,使用此語法:

Trig::createTable(); 

由於SIN_TABLECOS_TABLE表也是靜態的,使用的語法爲:

Trig::SIN_TABLE[120]; 
Trig::COS_TABLE[120]; 
+0

請將代碼格式化爲代碼,並且不要忘記分號 – doctorlove

0

最好的,讓你的您擁有單個靜態對象的類的表(非靜態)成員:

#include <cmath>       // include C++ header instead of C 

namespace trig {       // use a namespace instead of a class 
    const double pi = 4*std::atan2(1.,1.); // avoid pre-processor macros 
    namespace details {     // hide details in inner namespace 
    struct sin_cos_tables    // class holding tables 
    { 
     double SIN[360]; 
     double COS[360]; 
     sin_cos_tables()     // default constructor: set tables 
     { 
     const double fac = pi/180; 
     for(int angle = 0; angle != 360; ++angle) 
     { 
      SIN[angle] = std::sin(angle*fac); 
      COS[angle] = std::cos(angle*fac); 
     } 
     } 
    }; 
    static sin_cos_tables TABLES;  // static object constructed at start-up 
    } 
    static const double*SIN_TABLE = details::TABLES.SIN; // for your convenience 
    static const double*COS_TABLE = details::TABLES.COS; // (not really necessary) 
} 

int main() 
{ 
    double x = trig::SIN_TABLE[120]; 
} 

這樣,表格會在您的其他(非靜態)代碼運行之前自動創建。

+0

這個定義似乎是一個更好的解決方案。我從來沒有定義過一個命名空間,因此我必須稍微查看一下,但是我明白了靜態對象的含義。我可以問爲什麼我應該避免使用預處理器宏來定義PI?在什麼情況下宏將被優先考慮爲一個常量? – Corpsecreate

+0

請參閱http://stackoverflow.com/questions/9941107/what-are-the-major-advantages-of-const-versus-define-for-global-constants – Walter

+0

重新評論「避免預處理器宏」:它在這裏使用預處理器宏遠比自己輸入常量更可取,可能會造成拼寫錯誤,或者沒有爲相關平臺輸入足夠的數字。 (另一方面,所有上限通常意味着一個宏,所以變量不應該是'SIN'和'COS')。我不明白額外的靜態指針的重點。 –