【C言語】三角関数(sin・cos・tan)の使い方

三角関数の使い方解説ページアイキャッチ

このページでは、C言語での「三角関数の使い方」について解説していきます!

sin 関数・cos 関数・tan 関数

C言語では、数学等で利用した sin・cos・tan の計算を行う関数が標準ライブラリ関数として用意されています。

sin・cos・tan
#incldue <math.h>

double sin(double x);
double cos(double x);
double tan(double x);

sin 関数・cos 関数・tan 関数を利用するためには、math.h をインクルードしておく必要があるので注意してください。

MEMO

環境によっては sin 関数・cos 関数・tan 関数を利用するために libm のリンクが必要な場合があります

もしコンパイルをしてみて "Undefiend Reference....""未解決の外部シンボル...." みたいなエラーが出るようであれば、コンパイル時のオプションに -lm を指定してみてください

libm のリンクが行われてエラーを解決できると思います

例えば下記は、0 度から 359 度までの角度に対する sin 関数・cos 関数・tan 関数の結果を 20 度刻みで表示するプログラムのソースコードになります。

sin・cos・tanの結果表示
#include <stdio.h>
#include <math.h>

int main(void) {

    for (int degree = 0; degree < 360; degree+=20) {
        double rad = degree * M_PI / 180;

        printf("%3d : %4.2f %4.2f %4.2f\n", degree, sin(rad), cos(rad), tan(rad));
    }

    return 0;
}

実行結果は下記のようになります。

  0 : 0.00 1.00 0.00
 20 : 0.34 0.94 0.36
 40 : 0.64 0.77 0.84
 60 : 0.87 0.50 1.73
 80 : 0.98 0.17 5.67
100 : 0.98 -0.17 -5.67
120 : 0.87 -0.50 -1.73
140 : 0.64 -0.77 -0.84
160 : 0.34 -0.94 -0.36
180 : 0.00 -1.00 -0.00
200 : -0.34 -0.94 0.36
220 : -0.64 -0.77 0.84
240 : -0.87 -0.50 1.73
260 : -0.98 -0.17 5.67
280 : -0.98 0.17 -5.67
300 : -0.87 0.50 -1.73
320 : -0.64 0.77 -0.84
340 : -0.34 0.94 -0.36

ソースコードに登場する M_PI は円周率 π を表す定数マクロになります。このページのソースコードではこの M_PI を利用しますが、下記ページで解説しているとおり、math.h をインクルードしても M_PI が利用できない場合があるので注意してください。その場合は別途 M_PIPI を自身で定義する必要があります。

C言語で円周率を扱う方法の解説ページアイキャッチC言語で円周率πを扱う方法

引数は単位が「ラジアン」の角度

sin 関数・cos 関数・tan 関数ともに引数に指定するのは「角度」であり、その角度の単位は「ラジアン」である必要があります。単位が「度」の角度を引数に指定すると意図した結果が得られないので注意してください。

そのため、プログラム内で角度を「度」で扱っている場合、sin 関数・cos 関数・tan 関数を実行する前には事前に角度を「度」から「ラジアン」に変換する必要があります。

角度の単位を度からラジアンへ変換する様子

この角度の単位の変換方法に関しては下記ページで解説していますので、詳しく知りたい方はこちらをご参照しただければと思います。

度とラジアンの単位変換の方法の解説ページアイキャッチ度(度数法)⇔ラジアン(弧度法)の変換

スポンサーリンク

sin 関数・cos 関数・tan 関数の返却値

続いて sin 関数・cos 関数・tan 関数の返却値について確認していきましょう!

下の図のような、底辺の長さが a、高さが b、斜辺の長さが c、斜辺と底辺とがなす角の角度が θ 度の直角三角形で考えていきたいと思います。

三角関数の説明図1

また、θ の単位をラジアンに変換した角度を x としたいと思います。この x は下記の式により求めることが出来ます。

ラジアンへの変換
x = θ * M_PI / 180

上記で求めた x を引数に指定して sin(x)cos(x)tan(x) を実行した場合、返却値はそれぞれ下記のようになります。

  • sin(x)b / c
  • cos(x)a / c
  • tan(x)b / a

要は、sin 関数・cos 関数・tan 関数は「直角三角形における2辺の長さの比」を返却します。

三角関数の説明図2

sin 関数・cos 関数・tan 関数の使用例

これらの三角関数は、単に数式を解く上でも便利な関数ですが、図形や座標等を扱うプログラムで特に活躍します。

三角関数で三角形の面積を求める

例えば、下の図の三角形の面積について考えてみましょう!長さ d と長さ e と角度 x が分かっている場合、どのようにして三角形の面積は求められるでしょうか?(まずは、角度 x の単位は「ラジアン」で考えていきたいと思います)

三角関数を利用して三角形の面積を求める様子

このような三角形の面積は三角関数を利用することで簡単に求めることが出来ます。

まず、三角形に下の図のように補助線を入れれば、この補助線の長さが三角形の高さとなります。この高さを f としたいと思います。

三角関数を利用して三角形の面積を求める様子2

三角形の面積は 底辺の長さ * 高さ / 2 で求めることが出来ますので、上の図の三角形の面積は d * f / 2 により求めることができることになります。また、現状では d の長さは分かっているので、f を求められれば三角形の面積を求めることが出来ます。

さらに、青で色をつけた部分は直角三角形になりますね!したがって、sin(x) を実行すれば、f / e を返却値として得ることができることになります。これはつまり、sin(x) = f / e の等式が成立することになります。

三角関数を利用して三角形の面積を求める様子3

この等式の sin(x) = f / e の両辺に e を掛ければ f = e * sin(x) が成立することになり、また e の長さは分かっていますので、結局 fの長さは e * sin(x)で求めることが出来ることになります。したがって、下の図の三角形の面積は d * e * sin(x) / 2 により求めることができることになります。

三角関数を利用して三角形の面積を求める様子4

この三角形の面積を求めるプログラムは下記のように書くことが出来ます。

三角形の面積を求める
#include <stdio.h>
#include <math.h>

int main(void) {

    double d, e;
    double x;
    double s;

    /* 2辺の長さを設定 */
    d = 30;
    e = 25;

    /* 角度を設定 */
    x = M_PI / 6;

    /* 面積を計算して表示 */
    s = d * e * sin(x) / 2;
    printf("%f\n", s);

    return 0;
}

ここまで x を「ラジアン」の単位の角度を扱ってきましたが、もし、x の単位が「度」の場合は下記のように角度の単位を変換してから求める必要があるので注意してください。

三角形の面積を求める(角度が度の場合)
#include <stdio.h>
#include <math.h>

int main(void) {

    double d, e;
    int x;
    double rad_x;
    double s;

    /* 2辺の長さを設定 */
    d = 30;
    e = 25;

    /* 角度を設定 */
    x = 30;

    /* 角度をラジアンに変換 */
    rad_x = x * M_PI / 180;

    /* 面積を計算して表示 */
    s = d * e * sin(rad_x) / 2;
    printf("%f\n", s);

    return 0;
}

ポイントは、長さが不明の辺の長さを「三角関数の利用により求めているところ」です。

このように、三角関数を利用することで、直角三角形の「一辺の長さ」と「斜辺と底辺とがなす角の角度」から「他の辺の長さ」を求めることが可能です。これはここまで紹介した三角形の面積を求める場合だけでなく、図形や座標を扱う場合に大活躍するので覚えておくと良いと思います!

スポンサーリンク

三角関数で回転を行う

また、三角関数を利用して画像や図形の回転を行う事も可能です。画像の回転に関しては下記ページで詳しく解説していますので興味のある方は是非読んでみてください。

画像の回転の解説ページアイキャッチC言語で画像を回転

ここでは、簡単に下のような F を表す文字を回転するプログラム例を紹介しておきます。

            
   ******   
   ******   
   **       
   **       
   ******   
   ******   
   **       
   **       
   **       
   **       
        

例えば135度で回転すると F の文字が下記のように変化します(ちょっと一方に寄ってしまって見た目がイマイチになる回転角度もありますが…)。

            
     *      
     **     
      **    
       **   
       ***  
      ***** 
     ***  **
     **  ***
        *** 
       ***  
        *   

この F を表す文字の回転は、下記のプログラムで実現することが出来ます。

Fの回転
#include <stdio.h>
#include <math.h>

#define Y 12
#define X 12

static int F[Y][X] = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
    0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
    0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
    0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
    0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

static int rotated_F[Y][X];

void output(void) {
    for (int y = 0; y < Y; y++) {
        for (int x = 0; x < X; x++) {
            if (rotated_F[y][x] == 0) {
                /* 0の場合は空白を出力 */
                printf(" ");
            } else {
                /* 1の場合は*を出力 */
                printf("*");
            }
        }
        printf("\n");
    }
}

void rotate(int degree) {

    double mat[2][2];
    double db_x, db_y;
    int b_x, b_y;

    /* 回転行列の逆行列を作成 */
    mat[0][0] = cos(M_PI / 180 * degree);
    mat[0][1] = sin(M_PI / 180 * degree);
    mat[1][0] = -sin(M_PI / 180 * degree);
    mat[1][1] = cos(M_PI / 180 * degree);

    /* 回転後の全座標(x,y)に回転前の座標をコピーする */
    for (int y = 0; y < Y; y++) {
        for (int x = 0; x < X; x++) {
            
            /* 行列matと回転後座標(x,y)との積から回転前座標(db_x,db_y)を算出 */
            db_x = mat[0][0] * (x - X / 2) + mat[0][1] * (y - Y / 2);
            db_y = mat[1][0] * (x - X / 2) + mat[1][1] * (y - Y / 2);

            /* (db_x,db_y)に一番近い座標を算出 */
            b_x = round(db_x) + X / 2;
            b_y = round(db_y) + Y / 2;

            if (b_x < 0 || b_x >= X || b_y < 0 || b_y >= Y) {
                /* 回転前座標が配列外であれば0とする */
                rotated_F[y][x] = 0;
            } else {
                /* 回転後座標に回転前座標をコピー */
                rotated_F[y][x] = F[b_y][b_x];
            }
        }
    }
}

int main(void) {

    int degree;
    printf("angle(degree):");
    scanf("%d", &degree);

    if (degree < 0 || degree >= 360) {
        printf("0 - 359を入力してください\n");
        return 0;
    }
    
    rotate(degree);

    output();

    return 0;
}

この回転は、ほぼ前述で紹介した画像の回転と同じ仕組みで行っています(そのためソースコードの解説は省略させていただきます…)。もしかしたらソースコードを難しく感じるかもしれませんが、まずは三角関数を利用することでこういった回転も実現することができることを覚えておくと良いと思います!

その他三角関数でできること

三角関数を使ってゲームのキャラクターの動作等も実現することが出来ます。C言語始めたてでゲームを開発する機会はなかなかないかもしれませんが、三角関数はゲームプログラミング等でも活躍することは知っておくと良いと思います。

簡単なゲームのキャラクターの動作を三角関数でどのように実現しているかについては下記ページでも解説していますので、興味があれば読んでみてください(ソースコードはイメージしか載せていませんので注意してください)。

三角関数の重要性の解説ページアイキャッチプログラミングにおける三角関数の重要性

まとめ

このページでは、C言語での「三角関数(sin 関数・cos 関数・tan 関数)の使い方」について解説しました!

使用時の注意点は下記の3つだと思います。

  • 引数に指定する角度の単位は「ラジアン」
  • math.h をインクルードする
  • 必要に応してコンパイル(リンク)時に -lm を指定する

三角関数は単に数式を解くだけでなく、図形や画像を扱ったりゲームのキャラクター等の動作を実現したりするときにも活躍してくれる関数になります!

三角関数を使いこなせると、よりプログラミングを楽しめるようになりますので、ぜひ三角関数の使い方はマスターしておきましょう!

また、逆三角関数の atanatan2 については下記ページで解説しています。これらの関数は直角三角形の角度を算出するもので、こちらも非常に便利な関数なので是非読んでみてください!

【C言語】atan関数とatan2関数について解説(傾きor座標から角度を求める関数)

同じカテゴリのページ一覧を表示

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です