C言語では、平方根を求める標準的な方法としてsqrt関数が用意されています。
整数だけでなく小数の平方根も計算できますが、負の値を渡してはいけないなど、いくつか重要なルールがあります。
本記事では、C言語初心者の方に向けて、sqrtの基本から小数の平方根を安全に扱うポイント、さらに実践的な応用例まで順を追って解説します。
sqrt関数とは?
sqrtの役割と平方根の意味
平方根とは「ある数を2乗したとき、元の数になる値」のことです。
例えば、4の平方根は2です。
なぜなら2 * 2 = 4だからです。
同様に、9の平方根は3です。
数学的には、次のように表現できます。
- 数
aの平方根√aは、x^2 = aをみたす数xのこと
C言語のsqrt関数は、この平方根を計算するための標準関数です。
例えばsqrt(4.0)と書くと、結果として2.0が返されます。
C言語では、平方根計算は自分でアルゴリズムを書かなくても、sqrtを使えば簡単に利用できます。
これが最も重要なポイントです。
sqrtが定義されているヘッダファイル
sqrt関数は数値計算用の標準ライブラリであるmath.hに定義されています。
そのため、プログラムの先頭で次のようにincludeする必要があります。
#include <stdio.h>
#include <math.h> // sqrtなどの数学関数を使うために必要
この#include <math.h>を忘れると、コンパイル時に「宣言されていない関数を使っている」というエラーや警告が出ます。
また、多くの環境(GCCなど)では、sqrtを使うときにリンク時に数学ライブラリを指定する必要があります。
たとえば、ターミナルでコンパイルする場合は次のようにします。
gcc main.c -lm
ここで-lmは、mathライブラリ(libm)をリンクするオプションです。
IDE(Code::BlocksやVisual Studioなど)を使っている場合は、自動で設定されることが多いですが、コンパイルエラーが出たときは確認してみてください。
sqrtの書式と戻り値の型
C言語におけるsqrt関数の基本的な宣言は、次のようになっています。
double sqrt(double x);
ここから、以下のことが分かります。
- 引数の型は
double - 戻り値の型も
double - 引数
xには「平方根を求めたい数」を渡す
つまり、sqrtは常にdouble型の値を返す関数です。
整数を渡したときも、内部的にはdoubleに変換されて処理されます。
標準では、次のようなバリエーションも用意されています。
| 関数名 | 引数の型 | 戻り値の型 | 説明 |
|---|---|---|---|
sqrt | double | double | 通常の平方根関数 |
sqrtf | float | float | float専用の平方根関数 |
sqrtl | long double | long double | long double専用の平方根関数 |
初心者のうちは基本的にsqrtだけを覚えておけば十分です。
C言語でのsqrtの基本的な使い方
簡単なsqrtの使用例
まずは最もシンプルなsqrtの使い方を見てみます。
ここでは、固定の値の平方根を計算して表示します。
#include <stdio.h>
#include <math.h> // sqrtを使うために必要
int main(void) {
double x = 9.0; // 平方根を求めたい数
double result; // 結果を格納する変数
result = sqrt(x); // sqrtで平方根を計算
// 計算結果を表示
printf("sqrt(%f) = %f\n", x, result);
return 0;
}
sqrt(9.000000) = 3.000000
この例では、9.0の平方根として3.0が得られていることが確認できます。
変数を使ったsqrtの例
先ほどは定数の平方根を求めましたが、実際のプログラムでは変数に入っている値の平方根を計算することがほとんどです。
ユーザーから入力を受け取って、その平方根を計算する例を見てみましょう。
#include <stdio.h>
#include <math.h>
int main(void) {
double value; // ユーザーから入力してもらう値
double root; // 平方根を格納する変数
printf("平方根を求めたい数を入力してください: ");
scanf("%lf", &value); // %lfはdouble型の読み取り
root = sqrt(value); // valueの平方根を計算
printf("%f の平方根は %f です。\n", value, root);
return 0;
}
平方根を求めたい数を入力してください: 16
16.000000 の平方根は 4.000000 です。
このように、変数を使えば、さまざまな入力に対して柔軟に平方根を計算できます。
printfによる平方根の表示方法
printfで平方根の結果を表示するときは、書式指定子を正しく使うことが大切です。
sqrtの戻り値はdouble型なので、基本的には%fまたは%lfを使います。
小数点以下の桁数を指定したい場合は、次のように書きます。
#include <stdio.h>
#include <math.h>
int main(void) {
double x = 2.0;
double r = sqrt(x);
// デフォルトの表示(小数点以下6桁)
printf("sqrt(%f) = %f\n", x, r);
// 小数点以下2桁に丸めて表示
printf("sqrt(%f) を小数点以下2桁で表示: %.2f\n", x, r);
// 小数点以下10桁まで表示
printf("sqrt(%f) を小数点以下10桁で表示: %.10f\n", x, r);
return 0;
}
sqrt(2.000000) = 1.414214
sqrt(2.000000) を小数点以下2桁で表示: 1.41
sqrt(2.000000) を小数点以下10桁で表示: 1.4142135624
表示桁数を変えるだけで、同じ計算結果でも見え方が大きく変わることが分かります。
出力フォーマットは、用途に応じて調整すると良いです。
小数の平方根を安全に計算するポイント
小数を扱う型
平方根を計算する場面では、小数を扱うことがとても多いです。
例えば、2の平方根は1.4142...と無限に続く小数なので、int型では表現できません。
ここで重要になるのが、浮動小数点型です。
C言語には、主に次の3種類の浮動小数点型があります。
| 型 | 典型的なサイズ | 説明 |
|---|---|---|
float | 4バイト | 単精度。精度はやや低いが、メモリ使用量は少ない |
double | 8バイト | 倍精度。標準的に推奨される型 |
long double | 8〜16バイト程度 | 実装依存。より高精度になることが多い |
sqrtはdoubleを前提に設計されているので、特に理由がなければdoubleを使うのが無難です。
例えば、次のように書きます。
#include <stdio.h>
#include <math.h>
int main(void) {
double x = 2.0; // double型で宣言
double r = sqrt(x); // double型同士で扱う
printf("2.0 の平方根は %f です。\n", r);
return 0;
}
整数型(intなど)の変数にsqrtの結果を代入すると、小数点以下が切り捨てられてしまうので注意してください。
0以上の値だけにsqrtを使う
平方根の定義は「x^2 = aを満たす数x」でしたが、実数の範囲では、負の数aに対する平方根は存在しません。
そのため、C言語のsqrt関数に0未満の値を渡すと、結果は未定義(実行環境によって動作が異なる)になります。
多くの環境では、次のような挙動になります。
- 戻り値として
nan(Not a Number)が返される errnoにEDOM(範囲エラー)が設定される
しかし、初心者のうちは「sqrtに負の値を渡してはいけない」と覚えておく方が安全です。
例えば、次のコードは危険です。
#include <stdio.h>
#include <math.h>
int main(void) {
double x = -4.0; // 負の値
double r = sqrt(x); // 未定義動作になる可能性
printf("sqrt(%f) = %f\n", x, r);
return 0;
}
このプログラムの結果は、環境によって変わる可能性があります。
必ずしもエラーにならないので、バグに気付きにくい点が特に危険です。
そこで、次の節のように、事前に入力値を検証することが大切になります。
入力値の検証
ユーザーから入力された値や、他の計算結果をそのままsqrtに渡すのは危険です。
必ず「0以上かどうか」をチェックしてから平方根を計算するようにしましょう。
次の例では、ユーザー入力に対して検証を行い、安全に平方根を計算しています。
#include <stdio.h>
#include <math.h>
int main(void) {
double value;
double root;
printf("平方根を求めたい数を入力してください(0以上): ");
if (scanf("%lf", &value) != 1) {
// 入力が数値として読み取れなかった場合
printf("<mark style="background-color:rgba(0, 0, 0, 0);color:#cf2e2e" class="has-inline-color"><strong>数値の入力に失敗しました。</strong></mark>\n");
return 1;
}
// 0以上かどうかをチェック
if (value < 0.0) {
printf("<mark style="background-color:rgba(0, 0, 0, 0);color:#cf2e2e" class="has-inline-color"><strong>負の数の平方根は計算できません。</strong></mark>\n");
return 1;
}
root = sqrt(value); // ここまで来れば安全に呼び出せる
printf("%f の平方根は %f です。\n", value, root);
return 0;
}
実行例(安全な入力):
平方根を求めたい数を入力してください(0以上): 25
25.000000 の平方根は 5.000000 です。
実行例(負の数を入力した場合):
平方根を求めたい数を入力してください(0以上): -3
<mark style="background-color:rgba(0, 0, 0, 0);color:#cf2e2e" class="has-inline-color"><strong>負の数の平方根は計算できません。</strong></mark>
このように事前チェックを行うことで、「いつの間にか負の値が入り、結果が壊れる」といった不具合を未然に防ぐことができます。
0除算と混同しないための注意点
初心者の方が混乱しやすいポイントとして、0除算と平方根のエラーがあります。
1 / 0のような「0で割る」操作は、整数の場合でも浮動小数点の場合でも、ほぼ常に重大なエラー(未定義動作)になります。- 一方、
sqrt(0)は問題なく、結果は0となります。
つまり、sqrtに0を渡すことは安全であり、禁止されているのは「負の値」です。
両者を混同しないように注意してください。
次の例で違いを確認してみましょう。
#include <stdio.h>
#include <math.h>
int main(void) {
double a = 0.0;
double b = 4.0;
// sqrt(0) は安全
printf("sqrt(0.0) = %f\n", sqrt(a));
// 4 / 0 は危険(実行すると未定義動作)
// コメントアウトしてありますが、こういうコードは書かないようにしましょう。
// double div = b / a;
// printf("4.0 / 0.0 = %f\n", div);
return 0;
}
平方根における危険な入力は「負の数」であり、「0」は問題ないことを、しっかり区別して覚えると混乱が減ります。
実践的なsqrtの応用パターン
powとの違い(sqrtとpow(x, 0.5)の比較)
平方根は、指数の形で書くとx^(1/2)とも表せます。
そのため、C言語のpow関数を使ってpow(x, 0.5)と書いても、平方根を求めることができます。
#include <stdio.h>
#include <math.h>
int main(void) {
double x = 9.0;
double r1 = sqrt(x); // 専用のsqrt
double r2 = pow(x, 0.5); // powで平方根を表現
printf("sqrt(%f) = %f\n", x, r1);
printf("pow(%f, 0.5) = %f\n", x, r2);
return 0;
}
sqrt(9.000000) = 3.000000
pow(9.000000, 0.5) = 3.000000
多くの場合、これらは同じ結果になりますが、平方根を計算したいときはsqrtを使う方が良いです。
その理由としては次のようなものがあります。
- 意味が明確で、コードを読む人に「ここで平方根を計算している」とすぐ伝わる
- 最適化されていることが多く、
powより高速な場合がある - 間違いが少ない(
pow(x, 1/2)と書くと整数除算になってしまう、などの罠を避けられる)
特に、pow(x, 1/2)と書くと1/2が0になってしまいpow(x, 0)になってしまうという典型的なミスがあります。
平方根を計算したい場合は、必ずsqrt(x)を使うと決めておくと安全です。
三角形の斜辺を求める
sqrtの代表的な応用例として、直角三角形の斜辺の長さを求める問題があります。
直角三角形では、ピタゴラスの定理より次が成り立ちます。
- 辺の長さを
a、b、斜辺をcとすると、c = sqrt(a^2 + b^2)
これをC言語で実装してみます。
#include <stdio.h>
#include <math.h>
int main(void) {
double a, b; // 直角をはさむ2辺の長さ
double c; // 斜辺の長さ
printf("直角三角形の2辺の長さを入力してください。\n");
printf("a: ");
if (scanf("%lf", &a) != 1) {
printf("<mark style="background-color:rgba(0, 0, 0, 0);color:#cf2e2e" class="has-inline-color"><strong>aの入力に失敗しました。</strong></mark>\n");
return 1;
}
printf("b: ");
if (scanf("%lf", &b) != 1) {
printf("<mark style="background-color:rgba(0, 0, 0, 0);color:#cf2e2e" class="has-inline-color"><strong>bの入力に失敗しました。</strong></mark>\n");
return 1;
}
// 負の長さはありえないのでチェック
if (a < 0.0 || b < 0.0) {
printf("<mark style="background-color:rgba(0, 0, 0, 0);color:#cf2e2e" class="has-inline-color"><strong>辺の長さは0以上である必要があります。</strong></mark>\n");
return 1;
}
// c = sqrt(a^2 + b^2) を計算
c = sqrt(a * a + b * b);
printf("斜辺の長さは %f です。\n", c);
return 0;
}
直角三角形の2辺の長さを入力してください。
a: 3
b: 4
斜辺の長さは 5.000000 です。
この例では、実際の数学の公式をC言語でそのまま表現しているため、数式からコードへの変換の良い練習にもなります。
距離計算でのsqrt
sqrtは、2次元や3次元空間での距離計算にもよく使われます。
例えば、2次元平面上の2点(x1, y1)と(x2, y2)の距離は、次の式で表されます。
distance = sqrt((x2 - x1)^2 + (y2 - y1)^2)
ゲームプログラミングやシミュレーションなど、座標を扱う場面で頻出する式です。
C言語で実装すると、次のようになります。
#include <stdio.h>
#include <math.h>
int main(void) {
double x1, y1;
double x2, y2;
double dx, dy;
double distance;
printf("1つ目の点の座標(x1, y1)を入力してください。\n");
printf("x1: ");
if (scanf("%lf", &x1) != 1) {
printf("<mark style="background-color:rgba(0, 0, 0, 0);color:#cf2e2e" class="has-inline-color"><strong>x1の入力に失敗しました。</strong></mark>\n");
return 1;
}
printf("y1: ");
if (scanf("%lf", &y1) != 1) {
printf("<mark style="background-color:rgba(0, 0, 0, 0);color:#cf2e2e" class="has-inline-color"><strong>y1の入力に失敗しました。</strong></mark>\n");
return 1;
}
printf("2つ目の点の座標(x2, y2)を入力してください。\n");
printf("x2: ");
if (scanf("%lf", &x2) != 1) {
printf("<mark style="background-color:rgba(0, 0, 0, 0);color:#cf2e2e" class="has-inline-color"><strong>x2の入力に失敗しました。</strong></mark>\n");
return 1;
}
printf("y2: ");
if (scanf("%lf", &y2) != 1) {
printf("<mark style="background-color:rgba(0, 0, 0, 0);color:#cf2e2e" class="has-inline-color"><strong>y2の入力に失敗しました。</strong></mark>\n");
return 1;
}
// 差分を計算
dx = x2 - x1;
dy = y2 - y1;
// 距離 = sqrt(dx^2 + dy^2)
distance = sqrt(dx * dx + dy * dy);
printf("2点間の距離は %f です。\n", distance);
return 0;
}
1つ目の点の座標(x1, y1)を入力してください。
x1: 0
y1: 0
2つ目の点の座標(x2, y2)を入力してください。
x2: 3
y2: 4
2点間の距離は 5.000000 です。
このように、座標間の距離のような「長さ」を求める計算では、ほとんど必ずsqrtが登場します。
精度と誤差への注意
浮動小数点数で計算を行うと、必ずわずかな誤差が発生するという性質があります。
sqrtも浮動小数点計算なので、結果が「理論値と完全に一致する」とは限りません。
例えば、2.0の平方根は理論上1.414213562373...と無限に続きますが、コンピュータ内部では有限のビット数でしか表現できないため、どこかで丸められます。
次のコードで、誤差の様子を観察してみましょう。
#include <stdio.h>
#include <math.h>
int main(void) {
double x = 2.0;
double r = sqrt(x);
// 高い精度で表示してみる
printf("sqrt(2.0) = %.20f\n", r);
// r を2乗して元に戻るか確認
double back = r * r;
printf("sqrt(2.0) を2乗した値 = %.20f\n", back);
return 0;
}
sqrt(2.0) = 1.41421356237309514547
sqrt(2.0) を2乗した値 = 2.00000000000000044409
2乗し直しても、理論上は2.0に戻るはずですが、実際にはごくわずかにズレていることがわかります。
このような誤差は、浮動小数点数を扱う限り避けられません。
そのため、比較のときに「完全一致」を期待しないことが重要です。
例えば、次のような書き方は危険です。
// 悪い例: sqrt(2.0) * sqrt(2.0) が 2.0 と完全に等しいか比較している
if (sqrt(2.0) * sqrt(2.0) == 2.0) {
printf("等しい\n");
}
代わりに、「差がとても小さいなら等しいとみなす」という考え方をします。
具体的には、epsilonと呼ばれる小さな値を用意し、次のように比較します。
#include <stdio.h>
#include <math.h>
int main(void) {
double x = 2.0;
double r = sqrt(x);
double back = r * r;
double epsilon = 1e-10; // 許容する誤差の大きさ
if (fabs(back - x) < epsilon) {
printf("sqrt(2.0) * sqrt(2.0) は、2.0 とほぼ等しいとみなせます。\n");
} else {
printf("差が大きすぎます。\n");
}
return 0;
}
sqrt(2.0) * sqrt(2.0) は、2.0 とほぼ等しいとみなせます。
浮動小数点の世界では、「ほぼ等しい」と判断するための許容誤差を決めておくことがよく行われます。
sqrtを含む数値計算では、誤差があることを前提にプログラムを設計することが大切です。
まとめ
本記事では、C言語におけるsqrt関数の基本と、小数の平方根を安全に扱うための実践的なポイントを解説しました。
sqrtはmath.hに定義され、double型の平方根を返す標準関数です。
負の数に使わない、入力値を検証する、浮動小数点誤差を理解するといった注意点を押さえれば、斜辺の計算や距離計算など、さまざまな場面で安心して活用できます。
まずは簡単な例から試し、少しずつ応用範囲を広げていってください。
