C++で平方根、つまりルートを計算する場合は、標準ライブラリに用意されている std::sqrt() を使うのが基本です。
平方根とは、ある数に対して「2乗すると元の数になる値」のことです。
たとえば、4を2乗すると16になるため、16の平方根は4です。
C++では、自分で平方根の計算式を実装する必要はほとんどありません。
通常は、標準ライブラリの関数を使えば十分です。
基本は std::sqrt() を使う
std::sqrt() とは
std::sqrt() は、C++で平方根を求めるための標準関数です。
たとえば、16の平方根を求めると4になり、25の平方根を求めると5になります。
また、2の平方根のように割り切れない値の場合は、約1.41421のような小数の近似値が返されます。
C++で平方根を扱うときは、基本的にこの std::sqrt() を使うと考えてよいです。
<cmath> が必要
std::sqrt() を使うには、標準ヘッダーである <cmath> を読み込む必要があります。
<cmath> は、平方根、三角関数、絶対値、切り上げ、切り捨て、四捨五入など、数学的な処理を行うための関数がまとめられているヘッダーです。
平方根を計算するプログラムでは、基本的に <cmath> を使うと覚えておくとよいでしょう。
戻り値の型に注意する
平方根の結果は小数になることが多い
平方根の計算結果は、整数になるとは限りません。
たとえば、9の平方根は3ですが、10の平方根は約3.16228です。
このように、小数になるケースが多いため、平方根の結果は double などの浮動小数点型で受け取るのが一般的です。
整数を渡した場合でも、結果は小数として扱うのが自然です。
整数を渡しても結果は小数型で考える
たとえば、整数の10に対して平方根を求めると、結果は約3.16228になります。
このように、入力値が整数であっても、平方根の結果は整数とは限りません。
そのため、結果を整数型で受け取ると、小数部分が失われてしまう可能性があります。
基本的には、平方根の結果は double で扱うのが安全です。
結果を整数として使いたい場合
小数部分を捨てる場合
平方根の結果を整数として使いたい場合は、小数部分を捨てて整数化することがあります。
たとえば、10の平方根は約3.16228ですが、整数として扱うと3になります。
平方根の結果は0以上なので、この場合は実質的に「小数部分を切り捨てる」ような動きになります。
ただし、厳密には、C++で小数を整数に変換するときは「0方向への丸め」が行われます。
平方根の結果は負にならないため、通常は切り捨てと同じように考えて問題ありません。
四捨五入したい場合
平方根の結果を四捨五入したい場合は、切り捨てとは別の処理が必要です。
たとえば、10の平方根は約3.16228なので、四捨五入すると3になります。
一方、15の平方根は約3.87298なので、四捨五入すると4になります。
「整数部分だけがほしい」のか、「一番近い整数に丸めたい」のかによって、使う方法が変わります。
切り上げしたい場合
平方根の結果を必ず大きい方の整数にしたい場合は、切り上げを使います。
たとえば、10の平方根は約3.16228ですが、切り上げると4になります。
配列のサイズ計算や、必要な個数を求めるような場面では、切り上げが必要になることがあります。
切り捨て・切り上げ・四捨五入の違い
切り捨て
切り捨ては、小数部分を捨てて整数部分だけを残す方法です。
10の平方根は約3.16228なので、切り捨てると3になります。
「平方根以下の最大の整数」がほしい場合は、切り捨ての考え方を使います。
切り上げ
切り上げは、小数部分が少しでもあれば、次の整数に上げる方法です。
10の平方根は約3.16228なので、切り上げると4になります。
「平方根以上の最小の整数」がほしい場合に使います。
四捨五入
四捨五入は、最も近い整数に丸める方法です。
10の平方根は約3.16228なので3になりますが、15の平方根は約3.87298なので4になります。
表示用や概算値として使いたい場合に向いています。
負の数の平方根に注意する
実数では負の数の平方根は扱えない
通常の実数の範囲では、負の数の平方根は計算できません。
たとえば、-4の平方根は、実数では表せません。
C++で通常の数値型に対して負の値の平方根を求めると、結果が NaN になることがあります。
NaN は “Not a Number” の略で、「数値として表せない値」という意味です。
入力値をチェックするのが安全
ユーザーから入力された値の平方根を求める場合は、その値が負でないかを事前に確認するのが安全です。
負の数が入力された場合は、「実数の平方根は計算できない」として処理を分けるとよいでしょう。
特に初心者向けのプログラムや、ユーザー入力を扱うプログラムでは、このチェックを入れておくと予期しない結果を避けられます。
複素数として平方根を扱う場合
負の数の平方根は複素数なら扱える
実数では負の数の平方根を表せませんが、複素数を使えば扱えます。
たとえば、-4の平方根は、複素数では2iと表せます。
C++で複素数を扱う場合は、通常の数値型ではなく、複素数用の型を使います。
<complex> を使う
C++には複素数を扱うための <complex> という標準ヘッダーがあります。
負の数の平方根を複素数として計算したい場合は、<cmath> ではなく、複素数用の機能を使います。
ただし、通常のプログラミング学習や一般的な数値計算では、負の数は事前に除外して、実数の範囲で処理することが多いです。
float・double・long double の違い
基本は double でよい
C++では、小数を扱う型として主に float、double、long double があります。
一般的な計算では、double を使うのが標準的です。
精度と扱いやすさのバランスがよく、平方根の計算でもよく使われます。
初心者が平方根を扱う場合は、まず double を使うと考えて問題ありません。
float は精度が低め
float は double よりも使用するメモリが少ない一方で、精度は低めです。
ゲーム開発や大量の数値を扱う処理など、メモリ使用量や処理速度を意識する場面で使われることがあります。
ただし、通常の学習や一般的な計算では、無理に float を使う必要はありません。
long double はより高精度
long double は、double より高い精度を期待できる型です。
ただし、実際の精度は処理系によって異なることがあります。
また、通常のプログラムでは double で十分なことが多いため、特別に高精度が必要な場合に検討すればよいでしょう。
sqrtf・sqrt・sqrtl について
型ごとの平方根関数
C++には、型に応じた平方根関数があります。
float 向けには sqrtf、double 向けには sqrt、long double 向けには sqrtl が用意されています。
ただし、C++では通常、std::sqrt() を使えば、引数の型に応じて適切な処理が選ばれます。
通常は std::sqrt() で十分
初心者向けには、まず std::sqrt() を覚えれば十分です。
明確な理由がない限り、平方根を求めるときは std::sqrt() を使うと考えてよいでしょう。
型ごとの細かい関数を意識するのは、より高度な数値計算や、型を厳密に扱いたい場面になってからで問題ありません。
表示桁数を指定したい場合
小数点以下の桁数を整える
平方根の結果は小数になることが多いため、表示するときに桁数を指定したい場合があります。
たとえば、2の平方根は約1.41421356237ですが、表示上は小数点以下5桁だけ見せたい、あるいは10桁まで表示したいという場面があります。
このような場合は、出力時の表示形式を指定します。
fixed と組み合わせると小数点以下の桁数になる
C++では、表示精度を指定する機能があります。
ただし、注意点として、表示精度の指定は使い方によって意味が変わります。
fixed と組み合わせた場合は、「小数点以下何桁を表示するか」という意味になります。
一方、fixed を使わない場合は、「全体の有効数字を何桁にするか」という意味になります。
この違いは初心者が混乱しやすいポイントです。
浮動小数点誤差に注意する
平方根は近似値になることが多い
コンピュータで小数を扱う場合、すべての値を正確に表せるわけではありません。
たとえば、2の平方根は無理数なので、有限の桁数では正確に表せません。
そのため、C++では近似値として扱われます。
このような事情から、平方根の結果を使って厳密な比較を行う場合は注意が必要です。
小数同士を直接比較しない方がよい
小数計算では、本来同じ値になるはずでも、わずかな誤差が出ることがあります。
そのため、平方根の結果が特定の値と等しいかどうかを直接比較すると、期待通りにならないことがあります。
たとえば、計算上は3になるはずの値が、内部的には2.9999999999999996や3.0000000000000004のようになる可能性があります。
このような場合は、「完全に等しいか」ではなく、「十分近いか」で判定するのが一般的です。
誤差を許容して判定する
小数を比較する場合は、許容誤差を決めて、その範囲内であれば等しいとみなす方法がよく使われます。
たとえば、差が非常に小さければ「ほぼ等しい」と判断します。
この考え方は、平方根だけでなく、浮動小数点数を扱う多くの場面で重要です。
完全平方数の判定
完全平方数とは
完全平方数とは、ある整数を2乗して作れる整数のことです。
たとえば、1、4、9、16、25、36などは完全平方数です。
16は4を2乗した値なので、完全平方数です。
一方、10はどの整数を2乗しても作れないため、完全平方数ではありません。
小さい整数なら平方根を使って判定できる
小さい整数を扱う場合は、平方根を求めて、その値が整数になるかどうかを見ることで、完全平方数かどうかを判定できます。
たとえば、16の平方根は4なので、4を2乗して16に戻ることを確認すれば、完全平方数と判断できます。
大きな整数では注意が必要
大きな整数を扱う場合は、浮動小数点誤差に注意する必要があります。
平方根の計算結果が、本来は整数になるはずなのに、わずかにずれる可能性があります。
また、平方根の値を2乗して確認するときに、数が大きすぎると整数の範囲を超えてしまうことがあります。
これをオーバーフローと呼びます。
そのため、競技プログラミングや大きな整数を扱う処理では、単純な判定だけでは不十分な場合があります。
競技プログラミングでの整数平方根
整数平方根とは
整数平方根とは、平方根の小数部分を切り捨てた整数のことです。
たとえば、10の平方根は約3.16228なので、整数平方根は3です。
15の平方根は約3.87298なので、整数平方根も3です。
16の平方根はちょうど4なので、整数平方根は4です。
誤差補正が必要になることがある
競技プログラミングでは、大きな整数に対して平方根を求めることがあります。
このとき、std::sqrt() の結果をそのまま整数に変換すると、浮動小数点誤差によって1ずれる可能性があります。
そのため、いったん平方根の近似値を求めたあと、結果が正しい位置に来ているかを前後に補正する方法がよく使われます。
0の場合は特別に扱う
整数平方根を求める処理では、0を入力した場合に注意が必要です。
計算の途中で割り算を使う場合、0を割る形にならないようにしなければなりません。
そのため、0が入力された場合は、すぐに結果を0として返すようにするのが安全です。
これは、前回の説明で特に補足・修正した方がよいポイントです。
pow(x, 0.5) との違い
pow でも平方根は求められる
C++では、累乗を計算する関数を使って平方根を求めることもできます。
平方根は「2分の1乗」と考えることができるため、0.5乗を計算すれば平方根になります。
数学的には、この考え方は正しいです。
平方根なら sqrt を使う方がよい
ただし、C++で平方根を求めたい場合は、累乗関数ではなく std::sqrt() を使う方が適切です。
理由は、std::sqrt() の方が目的が明確だからです。
コードを読む人にとっても、「これは平方根を求めている」とすぐに分かります。
一方、0.5乗を使った書き方は、平方根を意味していることが少し分かりにくくなります。
可読性と意図の明確さが重要
プログラムでは、動けばよいだけでなく、読みやすさも重要です。
平方根を求めたいなら、平方根専用の関数を使う方が自然です。
そのため、通常は pow ではなく sqrt を使うと覚えておくとよいでしょう。
距離計算で平方根を使う場面
2点間の距離を求める
平方根は、座標上の2点間の距離を求めるときにもよく使われます。
2次元平面上に2つの点がある場合、その距離は、横方向の差と縦方向の差をそれぞれ2乗し、それらを足してから平方根を取ることで求められます。
これは三平方の定理を使った計算です。
hypot を使う方法もある
C++には、距離計算に便利な std::hypot() という関数もあります。
std::hypot() は、直角三角形の斜辺の長さを求める関数です。
単純に2乗して足して平方根を取る方法よりも、非常に大きな値や非常に小さな値を扱う場合に安全なことがあります。
そのため、2点間の距離を求める場合は、std::sqrt() だけでなく std::hypot() も選択肢になります。
よくある注意点
<cmath> を忘れない
std::sqrt() を使うには、<cmath> が必要です。
これを忘れると、コンパイルエラーになることがあります。
平方根や数学関数を使うときは、まず <cmath> を読み込むと覚えておくとよいです。
std:: を付ける
C++では、標準ライブラリの関数を使うときに std:: を付けるのが基本です。
環境によっては sqrt だけでも動くことがありますが、C++らしく明確に書くなら std::sqrt() とするのがよいです。
整数除算に注意する
平方根そのものとは少し違いますが、平方根に渡す値を計算するときに整数除算をしてしまうと、意図しない結果になることがあります。
たとえば、1を2で割った値の平方根を求めたい場合、整数同士で割ると結果が0になってしまいます。
小数として計算したい場合は、最初から小数として扱う必要があります。
前回内容の正確性について
大きな間違いはない
前回の内容は、C++で平方根を扱う説明として、おおむね正確です。
特に、std::sqrt() を使うこと、<cmath> が必要なこと、負の数に注意すること、浮動小数点誤差に注意することなどは正しく説明されています。
初心者向けの説明としても、実用的な説明としても大きな問題はありません。
補足した方がよい点はある
一方で、より正確にするなら、いくつか補足した方がよい点があります。
特に、表示桁数を指定する場合の fixed の有無、整数平方根で0を扱う場合の注意、大きな整数でのオーバーフローや誤差の問題は、追加で説明するとより安全です。
一番重要な修正点
最も重要な修正点は、競技プログラミング向けの整数平方根の説明で、0を入力した場合の扱いを明確にすることです。
0の平方根は0ですが、補正処理の中で割り算を使う場合、0で割る形にならないように注意が必要です。
そのため、整数平方根を実装する場合は、0を先に特別扱いするのが安全です。
まとめ
C++で平方根を計算する場合は、基本的に std::sqrt() を使います。
平方根の結果は小数になることが多いため、通常は double で扱うのが自然です。
負の数の平方根は、通常の実数計算では扱えないため、入力値が負でないかを確認する必要があります。
負の数を平方根として扱いたい場合は、複素数を使います。
また、平方根の結果を整数として扱う場合は、切り捨て、切り上げ、四捨五入のどれが必要なのかを明確にすることが大切です。
競技プログラミングや大きな整数を扱う場面では、浮動小数点誤差やオーバーフローにも注意が必要です。
特に整数平方根を求める場合は、0を入力したときの処理を忘れないようにしましょう。
全体として、前回の内容は大きく間違っていません。
ただし、より正確で安全な説明にするなら、表示精度、整数平方根、浮動小数点誤差、大きな整数の扱いについて補足すると、さらに信頼性の高い内容になります。
以上、C++での平方根(ルート)の計算方法についてでした。
最後までお読みいただき、ありがとうございました。
