HOWTO · C++
C++ 中的三角函式
本文演示瞭如何在 C++ 中使用 STL 的三角函式
本頁內容
C++ 在標準標頭檔 <cmath> 中提供正弦、餘弦、正切、反三角函式與雙曲函式。一般三角函式接受以弧度表示的角度,並回傳浮點數值。使用加上 std:: 限定的名稱,讓程式碼明確指向標準函式庫。
使用 std::sin、std::cos 和 std::tan 計算弧度角
呼叫 std::sin(angle)、std::cos(angle) 和 std::tan(angle),即可計算角度的正弦、餘弦和正切值。請包含 <cmath> 以取得這些函式的宣告。這些函式提供浮點型別的多載版本;回傳值會使用相對應的浮點型別(整數引數會轉換後交由浮點多載處理)。
執行以下範例:
本節中的程式碼以及顯示的標籤或輸出仍為英文。
#include <cmath>
#include <iomanip>
#include <iostream>
int main() {
const double angle = 1.0; // radians
std::cout << std::fixed << std::setprecision(6)
<< "sin(" << angle << ") = " << std::sin(angle) << '\n'
<< "cos(" << angle << ") = " << std::cos(angle) << '\n'
<< "tan(" << angle << ") = " << std::tan(angle) << '\n';
}
這次執行觀察到的輸出如下:
sin(1.000000) = 0.841471
cos(1.000000) = 0.540302
tan(1.000000) = 1.557408
引數代表一弧度。std::fixed 和 std::setprecision(6) 會將每個回傳值格式化為小數點後六位。
使用反三角函式求回角度
使用 std::asin(x) 從正弦值求回角度、使用 std::acos(x) 從餘弦值求回角度,或使用 std::atan(x) 從正切值求回角度。這些函式的結果都以弧度表示。asin 接受介於 -1 和 1 之間(含端點)的值,並回傳介於 [-π/2, π/2] 的角度;acos 的輸入範圍相同,回傳角度則介於 [0, π]。atan 接受任何有限實數,並回傳介於 (-π/2, π/2) 的角度。
若方向由兩個座標描述,請使用 std::atan2(y, x)。與 atan(y / x) 不同,這個函式會根據兩個引數的正負號判斷象限,不需要先將座標相除。結果是以弧度表示的角度,通常介於 [-π, π];端點的確切表示方式可能取決於輸入的帶符號零值。
反函式回傳的是主值角度,不是所有可能產生原始數值的角度。例如,好幾個角度可能有相同的正弦值,因此只用 asin 無法求回主值範圍以外的原始角度。選擇最後的角度時,請一併考量問題中的幾何關係與象限資訊。
使用雙曲函式計算雙曲值
std::sinh、std::cosh 和 std::tanh 分別計算雙曲正弦、雙曲餘弦和雙曲正切。這些函式由指數函式定義,不能取代 std::sin、std::cos 和 std::tan:它們接受的是實數值,而非圓上的角度,且值域也不同。例如,cosh(x) 至少為 1,一般餘弦則介於 -1 和 1 之間。
反雙曲函式為 std::asinh、std::acosh 和 std::atanh。它們的實數定義域各不相同:asinh 接受任何實數輸入;acosh 要求輸入至少為 1;atanh 則要求輸入嚴格介於 -1 和 1 之間。處理雙曲關係時請使用這些函式;一般三角函式名稱前加上 a,並不代表就能取得對應的反雙曲函式。
處理角度單位、定義域與浮點結果
C++ <cmath> 的三角函式都要求使用弧度。將角度轉為弧度的公式是 radians = degrees * π / 180;例如,90 度等於 π/2 弧度。在可攜式 C++ 中,可以用 std::acos(-1.0) 取得 π,或自行定義所需常數,因為 M_PI 並非標準 C++ 名稱。
反函式的輸入必須位於各自的實數定義域內。只有在符合應用程式所依據的數學情境時,才檢查或限制輸入值:若值只因累積的捨入誤差而略微超出 [-1, 1],限制範圍可能有幫助;但不應藉此掩蓋真正超出範圍的輸入。定義域錯誤的處理方式取決於 C++ 數學函式庫的錯誤行為與實作;這並非未定義行為。如果應用程式需要區分有效結果與數學錯誤,請參閱 math_errhandling,並檢查實作所支援的相關錯誤指標。
在 π/2 的奇數倍附近,std::tan 的值會急遽增大;在數學上的極點處,它沒有有限的實數值。浮點數近似的極點可能產生很大的有限值,而不是明確的錯誤訊號。如果應用程式需要處理接近極點的情況,請依照需求與容許誤差檢查輸入。
浮點計算都是近似值。例如,std::sin(std::acos(-1.0)) 的結果可能接近零,但不會恰好等於零。比較計算結果時,請使用符合應用程式需求的容許誤差,而非直接比較是否完全相等。一般計算可使用 double;只有在確實需要較高精度且實作支援時,才選用更寬的型別。優先使用標準函式庫,避免手寫近似演算法;若要重複使用某個計算值,請先將它存起來。