C++で数値の二乗を計算する方法について

AI実装検定のご案内

C++で数値の二乗を計算する場合は、同じ数値を掛け合わせる方法が基本です。

二乗とは、ある数値をその数値自身で掛ける計算を指します。

たとえば、5の二乗は次のとおりです。

5 × 5 = 25

C++では、掛け算を表す*演算子を使って二乗を計算します。

#include <iostream>

int main()
{
    int number = 5;
    int result = number * number;

    std::cout << result << '\n';

    return 0;
}

実行結果は次のとおりです。

25

単純な二乗であれば、number * numberと記述する方法が最も分かりやすく、整数型や浮動小数点型にも利用できます。

目次

整数の二乗を計算する方法

int型の整数を二乗する

小さな整数を二乗する場合は、int型を使用できます。

#include <iostream>

int main()
{
    int number = 8;
    int square = number * number;

    std::cout << number
              << "の二乗は"
              << square
              << "です。\n";

    return 0;
}

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

8の二乗は64です。

number * numberでは、変数numberの値を同じ値同士で掛け合わせています。

負の整数を二乗する

負の整数も、同じ数値を掛け合わせることで二乗できます。

#include <iostream>

int main()
{
    int number = -4;
    int result = number * number;

    std::cout << result << '\n';

    return 0;
}

実行結果は次のとおりです。

16

負の数同士を掛けると正の数になるため、-4の二乗は16です。

数値を直接記述する場合は、かっこを付けると意図が分かりやすくなります。

int result = (-4) * (-4);

小数の二乗を計算する方法

double型を使って二乗する

小数を二乗する場合は、double型やfloat型を使用します。

#include <iostream>

int main()
{
    double number = 2.5;
    double square = number * number;

    std::cout << square << '\n';

    return 0;
}

実行結果は次のとおりです。

6.25

精度を重視する一般的な計算では、floatよりも表現できる桁数が多いdoubleがよく使用されます。

一方、画像処理やゲーム、GPUを利用する計算などでは、メモリ使用量や処理性能を考慮してfloatが選ばれる場合もあります。

浮動小数点数には誤差が生じることがある

floatdoubleは、多くの小数を内部で完全には表現できません。

そのため、二乗結果にわずかな丸め誤差が含まれることがあります。

#include <iomanip>
#include <iostream>

int main()
{
    double number = 0.1;
    double result = number * number;

    std::cout << std::setprecision(17)
              << result
              << '\n';

    return 0;
}

環境によっては、次のような値が表示されます。

0.010000000000000002

数学上は0.01ですが、浮動小数点数の内部表現によって微小な誤差が発生します。

これは二乗に限らず、浮動小数点計算全般に共通する性質です。

std::pow関数で二乗を計算する方法

std::powの基本的な使い方

C++では、<cmath>ヘッダーに定義されているstd::pow関数を使って累乗を計算できます。

#include <cmath>
#include <iostream>

int main()
{
    double number = 5.0;
    double result = std::pow(number, 2.0);

    std::cout << result << '\n';

    return 0;
}

実行結果は次のとおりです。

25

std::powの基本的な書式は次のとおりです。

std::pow(底, 指数)

第1引数に底、第2引数に指数を指定します。

たとえば、2の3乗は次のように計算できます。

double result = std::pow(2.0, 3.0);

計算結果は8です。

単純な二乗では掛け算を使う

std::pow(number, 2.0)でも二乗は計算できます。

ただし、単純な二乗であれば、通常は次の書き方のほうが分かりやすいでしょう。

double result = number * number;

number * numberは、同じ値を掛け合わせていることがコードから直接読み取れます。

また、整数の二乗を整数型として扱いたい場合も、掛け算のほうが戻り値の型を管理しやすくなります。

整数の二乗にstd::powを使う場合の注意点

次のコードでも、結果として25を得られることがあります。

int result = std::pow(5, 2);

ただし、std::powは一般的な累乗計算を行う関数であり、整数専用の二乗関数ではありません。

浮動小数点型の計算結果が整数型へ変換される場合もあるため、整数の二乗には次の書き方が適しています。

int result = 5 * 5;

単純な整数の二乗であれば、std::powを使う必要はありません。

平方根にはstd::sqrtを使う

std::powを使うと、次のように平方根に相当する計算もできます。

double result = std::pow(number, 0.5);

ただし、平方根を求める場合は、専用のstd::sqrt関数を使用するのが基本です。

#include <cmath>

double result = std::sqrt(number);

専用関数を使うことで、何を計算しているのかがコードから明確に分かります。

C++には二乗専用の演算子がない

^は二乗を意味しない

C++では、^は累乗演算子ではありません。

^は、ビット単位の排他的論理和を行うXOR演算子です。

そのため、次のコードは5の二乗を計算しません。

int result = 5 ^ 2;

この式の結果は25ではなく、7になります。

2進数で表すと、次のように計算されます。

5     = 0101
2     = 0010
5 ^ 2 = 0111

0111を10進数に変換すると7です。

二乗を計算する場合は、次のように記述します。

int result = 5 * 5;

変数を使う場合は、次のようになります。

int result = number * number;

**演算子も使用できない

Pythonなどでは、**を累乗演算子として使用します。

result = 5 ** 2

しかし、C++には**という累乗演算子はありません。

次のコードはコンパイルエラーになります。

int result = 5 ** 2;

C++で二乗を計算する場合は、掛け算またはstd::powを使用します。

関数を作って二乗を計算する方法

整数用の二乗関数を作る

プログラム内で二乗計算を何度も行う場合は、関数としてまとめると便利です。

#include <iostream>

int square(int number)
{
    return number * number;
}

int main()
{
    std::cout << square(4) << '\n';
    std::cout << square(7) << '\n';

    return 0;
}

実行結果は次のとおりです。

16
49

関数にすることで、二乗計算の目的が明確になり、コードの重複も減らせます。

小数用の二乗関数を作る

小数の二乗を計算する場合は、引数と戻り値をdouble型にします。

#include <iostream>

double square(double number)
{
    return number * number;
}

int main()
{
    double result = square(1.5);

    std::cout << result << '\n';

    return 0;
}

実行結果は次のとおりです。

2.25

テンプレート関数で複数の型に対応する

基本的なテンプレート関数

整数用と小数用で別々の関数を作ると、似たコードが増えてしまいます。

関数テンプレートを使用すると、複数の型に対応した二乗関数を作成できます。

#include <iostream>

template <typename T>
T square(T number)
{
    return number * number;
}

int main()
{
    std::cout << square(5) << '\n';
    std::cout << square(2.5) << '\n';

    return 0;
}

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

25
6.25

square(5)ではTint型として扱われます。

square(2.5)ではTdouble型として扱われます。

この関数は、一般的な整数型や浮動小数点型に利用できます。

autoを戻り値に使う方法

乗算結果の型をそのまま戻したい場合は、戻り値にautoを使用できます。

template <typename T>
constexpr auto square(T number)
{
    return number * number;
}

この書き方では、number * numberの結果から戻り値の型が推論されます。

ただし、初心者向けのコードでは、戻り値をTと明示する書き方でも問題ありません。

数値型では値渡しが分かりやすい

次のようにconst T&で受け取ることもできます。

template <typename T>
T square(const T& number)
{
    return number * number;
}

しかし、intdoubleのような基本的な数値型はコピーの負担が小さいため、単純な二乗関数では値渡しのほうが分かりやすいでしょう。

template <typename T>
T square(T number)
{
    return number * number;
}

constexprで二乗を計算する方法

コンパイル時に計算できる関数を作る

constexprを付けた関数は、条件を満たす場合にコンパイル時に評価できます。

#include <iostream>

constexpr int square(int number)
{
    return number * number;
}

int main()
{
    constexpr int result = square(5);

    std::cout << result << '\n';

    return 0;
}

この例では、square(5)の結果をコンパイル時に求めることができます。

constexprは実行時にも使用できる

constexpr関数は、必ずコンパイル時に計算されるわけではありません。

実行時に入力された値を渡す場合は、通常の関数として実行時に評価されます。

#include <iostream>

constexpr int square(int number)
{
    return number * number;
}

int main()
{
    int number = 0;
    std::cin >> number;

    int result = square(number);

    std::cout << result << '\n';

    return 0;
}

constexprは、コンパイル時に評価できる場合は定数式として利用でき、実行時の値にも対応できます。

ラムダ式で二乗を計算する方法

整数用のラムダ式

二乗計算を限られた範囲でのみ使う場合は、ラムダ式として定義できます。

#include <iostream>

int main()
{
    auto square = [](int number)
    {
        return number * number;
    };

    std::cout << square(6) << '\n';

    return 0;
}

実行結果は次のとおりです。

36

auto引数で複数の型に対応する

C++14以降では、ラムダ式の引数にautoを使用できます。

#include <iostream>

int main()
{
    auto square = [](auto number)
    {
        return number * number;
    };

    std::cout << square(6) << '\n';
    std::cout << square(1.5) << '\n';

    return 0;
}

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

36
2.25

ラムダ式は、二乗処理をその場だけで使用したい場合に適しています。

整数を二乗するときのオーバーフロー

int型の範囲を超えることがある

整数を二乗すると、元の数値よりも急速に値が大きくなります。

そのため、計算結果がint型の表現範囲を超えることがあります。

#include <iostream>

int main()
{
    int number = 50000;
    int result = number * number;

    std::cout << result << '\n';

    return 0;
}

数学上、50000の二乗は次の値です。

2,500,000,000

一般的な32ビットのint型では、この値を表現できません。

符号付き整数の計算結果が型の範囲を超えると、C++では未定義動作になります。

単に最大値を超えた分だけ小さな値へ戻ると決めつけることはできません。

long long型を使う

より大きな整数を扱う場合は、long long型を使用できます。

#include <iostream>

int main()
{
    long long number = 50000;
    long long result = number * number;

    std::cout << result << '\n';

    return 0;
}

実行結果は次のとおりです。

2500000000

ただし、long longにも表現できる上限があります。

非常に大きな数値を二乗する場合は、long longでもオーバーフローする可能性があります。

掛け算の前に型を変換する

元の変数がint型の場合は、掛け算を行う前にlong long型へ変換する必要があります。

#include <iostream>

int main()
{
    int number = 50000;

    long long result =
        static_cast<long long>(number) * number;

    std::cout << result << '\n';

    return 0;
}

次のコードでは、右辺の掛け算が先にint型で行われます。

long long result = number * number;

代入先がlong long型であっても、掛け算を行った時点でオーバーフローしていれば問題を防げません。

少なくとも一方の値を、計算前にlong long型へ変換する必要があります。

long long result =
    static_cast<long long>(number) * number;

次のように1LLを掛ける方法もあります。

long long result = 1LL * number * number;

1LLlong long型の整数リテラルです。

ただし、型変換の意図を明確にしたい場合は、static_castを使う書き方が分かりやすいでしょう。

unsigned型を二乗するときの注意点

符号なし整数は剰余算術になる

符号なし整数の計算結果が表現範囲を超えた場合は、その型の範囲に応じた剰余算術になります。

簡単に言えば、最大値の次が0へ戻るような動作です。

#include <iostream>

int main()
{
    unsigned int number = 70000;
    unsigned int result = number * number;

    std::cout << result << '\n';

    return 0;
}

符号なし整数の動作は、符号付き整数のオーバーフローとは異なり、C++の仕様で定義されています。

ただし、数学上の二乗結果がそのまま得られるとは限りません。

大きな値を扱う場合は、より表現範囲の広い型を選ぶ必要があります。

unsigned intが必ず32ビットとは限らない

多くの環境ではunsigned intは32ビットですが、C++の仕様上、必ず32ビットと決まっているわけではありません。

そのため、特定のビット数を前提にした説明や計算を行う場合は、使用環境の型の大きさを確認する必要があります。

型の最大値は、std::numeric_limitsで確認できます。

#include <iostream>
#include <limits>

int main()
{
    std::cout
        << std::numeric_limits<unsigned int>::max()
        << '\n';

    return 0;
}

浮動小数点数を比較するときの注意点

計算結果を安易に==で比較しない

浮動小数点演算で得られた値には、丸め誤差が含まれる可能性があります。

そのため、数学的に近い値かどうかを判定する目的で==を使用すると、期待どおりにならない場合があります。

double result = 0.1 * 0.1;

if (result == 0.01)
{
    // 必ず期待どおりになるとは限らない
}

許容できる誤差を設定して比較する方法があります。

#include <cmath>
#include <iostream>

int main()
{
    double result = 0.1 * 0.1;
    double expected = 0.01;
    double tolerance = 1e-12;

    if (std::abs(result - expected) < tolerance)
    {
        std::cout << "ほぼ等しい\n";
    }

    return 0;
}

絶対誤差と相対誤差を使い分ける

固定された絶対誤差だけでは、非常に大きな値や小さな値を適切に比較できない場合があります。

値の規模が幅広い場合は、絶対誤差と相対誤差を組み合わせる方法があります。

#include <algorithm>
#include <cmath>

bool nearlyEqual(
    double a,
    double b,
    double relativeTolerance = 1e-12,
    double absoluteTolerance = 1e-12)
{
    double difference = std::abs(a - b);

    if (difference <= absoluteTolerance)
    {
        return true;
    }

    return difference <=
        relativeTolerance *
        std::max(std::abs(a), std::abs(b));
}

適切な許容誤差は、扱う値の大きさや用途によって異なります。

金額、測定値、画像処理、物理計算などでは、それぞれ異なる基準が必要です。

なお、浮動小数点数に対する==が常に誤りというわけではありません。

完全一致を確認したい処理では、==が適切な場合もあります。

入力された数値の二乗を計算する方法

標準入力から数値を受け取る

ユーザーが入力した数値の二乗を表示するプログラムは、次のように記述できます。

#include <iostream>

int main()
{
    double number = 0.0;

    std::cout << "数値を入力してください: ";
    std::cin >> number;

    double result = number * number;

    std::cout << number
              << "の二乗は"
              << result
              << "です。\n";

    return 0;
}

入力例は次のとおりです。

数値を入力してください: 12

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

12の二乗は144です。

入力エラーを確認する

数値以外の文字列が入力される可能性もあります。

std::cinの状態を確認すると、入力エラーに対応できます。

#include <iostream>

int main()
{
    double number = 0.0;

    std::cout << "数値を入力してください: ";

    if (!(std::cin >> number))
    {
        std::cerr
            << "正しい数値を入力してください。\n";

        return 1;
    }

    std::cout << "二乗は"
              << number * number
              << "です。\n";

    return 0;
}

数値として解釈できない入力が行われた場合は、エラーメッセージを表示して終了します。

配列の要素を二乗する方法

範囲for文を使う

配列内の数値を順番に二乗する場合は、範囲for文を使用できます。

#include <iostream>

int main()
{
    int numbers[] = {1, 2, 3, 4, 5};

    for (int number : numbers)
    {
        std::cout << number * number << '\n';
    }

    return 0;
}

実行結果は次のとおりです。

1
4
9
16
25

元の配列を書き換える

配列の要素自体を二乗後の値に変更する場合は、参照を使用します。

#include <iostream>

int main()
{
    int numbers[] = {1, 2, 3, 4, 5};

    for (int& number : numbers)
    {
        number *= number;
    }

    for (int number : numbers)
    {
        std::cout << number << '\n';
    }

    return 0;
}

int&で受け取ることで、配列の各要素そのものを書き換えています。

std::vectorの要素を二乗する方法

元のvectorを書き換える

可変長の数値データを扱う場合は、std::vectorが便利です。

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> numbers = {2, 4, 6, 8};

    for (int& number : numbers)
    {
        number *= number;
    }

    for (int number : numbers)
    {
        std::cout << number << '\n';
    }

    return 0;
}

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

4
16
36
64

別のvectorへ結果を保存する

元の値を残したまま、別のstd::vectorへ二乗結果を保存することもできます。

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> numbers = {2, 4, 6, 8};
    std::vector<int> squares;

    squares.reserve(numbers.size());

    for (int number : numbers)
    {
        squares.push_back(number * number);
    }

    for (int square : squares)
    {
        std::cout << square << '\n';
    }

    return 0;
}

reserveを使って必要な容量をあらかじめ確保すると、要素追加に伴うメモリの再確保を減らせます。

std::transformで要素を二乗する方法

別のコンテナへ結果を出力する

標準ライブラリのstd::transformを使うと、各要素へ同じ変換処理を適用できます。

#include <algorithm>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> numbers = {1, 2, 3, 4};
    std::vector<int> squares(numbers.size());

    std::transform(
        numbers.begin(),
        numbers.end(),
        squares.begin(),
        [](int number)
        {
            return number * number;
        }
    );

    for (int square : squares)
    {
        std::cout << square << '\n';
    }

    return 0;
}

実行結果は次のとおりです。

1
4
9
16

元のコンテナを直接書き換える

入力先と出力先に同じ範囲を指定すると、元のstd::vectorを書き換えられます。

std::transform(
    numbers.begin(),
    numbers.end(),
    numbers.begin(),
    [](int number)
    {
        return number * number;
    }
);

単純な処理では範囲for文のほうが読みやすい場合もあります。

一方、複数の標準アルゴリズムを組み合わせるコードでは、std::transformが適しています。

複素数を二乗する方法

std::complexと掛け算を使う

C++では、<complex>ヘッダーを使って複素数を扱えます。

複素数も*演算子で二乗できます。

#include <complex>
#include <iostream>

int main()
{
    std::complex<double> number(2.0, 3.0);
    std::complex<double> result = number * number;

    std::cout << result << '\n';

    return 0;
}

2 + 3iを二乗すると、次のようになります。

(2 + 3i)²
= 4 + 12i + 9i²
= -5 + 12i

一般的には、次の形式で表示されます。

(-5,12)

複素数にstd::powを使う

std::complexに対してもstd::powを使用できます。

std::complex<double> result =
    std::pow(number, 2);

ただし、単純な二乗であれば、次の掛け算のほうが直接的です。

auto result = number * number;

二乗を計算する方法の選び方

単純な二乗には掛け算を使う

整数や小数を単純に二乗する場合は、次の書き方が基本です。

auto result = number * number;

処理内容が分かりやすく、整数型や浮動小数点型にも自然に使用できます。

指数が変わる場合はstd::powを使う

二乗だけでなく、3乗や小数乗なども扱う場合はstd::powが適しています。

double square = std::pow(number, 2.0);
double cube = std::pow(number, 3.0);
double fractionalPower = std::pow(number, 1.5);

平方根を求める場合は、std::pow(number, 0.5)よりstd::sqrtを使うほうが明確です。

double squareRoot = std::sqrt(number);

繰り返し使う場合は関数化する

プログラム内で二乗計算を何度も使用する場合は、関数としてまとめると読みやすくなります。

template <typename T>
constexpr auto square(T number)
{
    return number * number;
}

関数名から処理の目的が分かるため、コードの可読性も向上します。

大きな整数では型の範囲を確認する

整数を二乗すると値が急速に大きくなるため、オーバーフローに注意が必要です。

元の値がint型で、結果をlong long型として計算したい場合は、掛け算の前に型を変換します。

long long result =
    static_cast<long long>(number) * number;

ただし、long longにも上限があるため、非常に大きな入力値では事前の範囲確認が必要です。

C++で数値の二乗を計算する方法のまとめ

C++で数値の二乗を計算する最も基本的な方法は、同じ数値を掛け合わせることです。

int result = number * number;

任意の指数を扱う場合は、<cmath>ヘッダーのstd::powを使用できます。

double result = std::pow(number, 2.0);

ただし、単純な二乗であれば、std::powよりもnumber * numberのほうが処理内容を直接表現できます。

また、C++の^は累乗演算子ではなく、XOR演算子です。

int result = 5 ^ 2;

このコードでは、5の二乗は計算できません。

整数を二乗する場合は、計算結果が型の範囲を超えないように注意する必要があります。

元の値がint型の場合は、掛け算を行う前にlong long型へ変換します。

long long result =
    static_cast<long long>(number) * number;

小数を二乗する場合は、浮動小数点数特有の丸め誤差にも注意が必要です。

基本的には、単純な二乗には掛け算、指数が変化する累乗計算にはstd::pow、繰り返し使用する場合は関数化というように、目的に応じて使い分けるとよいでしょう。

以上、C++で数値の二乗を計算する方法についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次