べき乗を求める | Programming Place Plus C言語編 逆引き

トップページC言語編逆引き

このページの概要

以下は目次です。

目的

ある数のべき乗(累乗)を求めたいとします。

べき乗の計算では、結果が非常に巨大な数になることがあるため、使っている型で表現しきれなくなることがあります。こういったエラーをきちんと検出できるように関数化してみます。

/*
    べき乗を求める

    引数
        x: 底
        y: 指数
        result: x を y乗した結果を受け取るメモリアドレス。ヌルポインタは不可。

    戻り値
        成否。false が返された場合、result の内容は不定。

    注意
        x、y がともに 0 の場合の結果は 1 とする。
*/
bool power(double x, double y, double* result);

また、0 の 0乗は、文脈によって定義が異なるので(参考リンク1)、結果を明確に決めておいた方がいいでしょう。ここでは、1 を返すことにします。

方法①(標準ライブラリ関数を使う)

標準ライブラリには、べき乗を求める pow関数と、その型違いのバージョンがあります。

double pow(double x, double y);
float powf(float x, float y);
long double powl(long double x, long double y);

それぞれ、x の y乗を計算して、結果を戻り値で返します。

整数型のものがないので、整数のべき乗を求めるのなら、基本的には pow関数を選ぶことになります。

【上級】結果を整数型にしなければならないのなら、丸め関数(第48章)を検討しましょう。普通に整数型へ型変換した場合に、変換後の型で表現できないと、未定義の動作になってしまいます(第21章)。

ごく単純には、次のように使えます。

double x = pow(2.0, 3.0);  // 2 の 3乗

この例のように、結果が確実に表現でき、エラーが起こる余地がない使い方なら良いのですが、そうでないなら備えが必要です。

pow系の関数は、以下の場合にエラーを発生させます。

  1. x が負数で、y が整数でない場合、定義域エラー
  2. x が 0 で、y が 0 以下の場合、定義域エラー。あるいは値域エラー
  3. 結果が表現できない場合、値域エラー

数学系関数が発生させるエラーについての詳細は、第48章を参照してください。ここでは、これらのエラーを検出するように関数化します。

#include <assert.h>
#include <errno.h>
#include <float.h>
#include <math.h>
#include <stdbool.h>
#include <stdio.h>

/*
    べき乗を求める

    引数
        x: 底
        y: 指数
        result: x を y乗した結果を受け取るメモリアドレス。ヌルポインタは不可。

    戻り値
        成否。false が返された場合、result の内容は不定。

    注意
        x、y がともに 0 の場合の結果は 1 とする。
*/
bool power(double x, double y, double* result)
{
    assert(result != NULL);

    if (x == 0.0 && y == 0.0) {
        *result = 1.0;
        return true;
    }

    errno = 0;
    *result = pow(x, y);
    if (errno == EDOM) {
        return false;
    }
    else if (errno == ERANGE) {
        return false;
    }

    return true;
}

int main(void)
{
    double result;

    if (power(2.0, 4.0, &result)) {
        printf("%lf\n", result);
    }
    else {
        puts("error");
    }

    if (power(DBL_MAX, 2.0, &result)) {
        printf("%lf\n", result);
    }
    else {
        puts("error");
    }

    if (power(0.0, 0.0, &result)) {
        printf("%lf\n", result);
    }
    else {
        puts("error");
    }
}

実行結果:

16.000000
error
1.000000


参考リンク

  1. 0の0乗 | Wikipedia


更新履歴



逆引きのトップページへ

C言語編のトップページへ

Programming Place Plus のトップページへ



はてなブックマーク に保存 Pocket に保存 Facebook でシェア
X で ポストフォロー LINE で送る noteで書く
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー
先頭へ戻る