閉じる

C言語のべき乗をpowで計算する方法と注意点(math.h)

C言語でべき乗を計算するには、標準ライブラリのmath.hが提供するpow関数を使います。

C言語にはべき乗演算子がないため、powの正しい使い方と注意点を知ることがとても重要です。

本記事では、基本的な使い方から型の扱いよくある誤り、そして実行可能なサンプルまで丁寧に解説します。

powの基本

powとは?

powは、底(base)を指数(exponent)で累乗した結果を返す関数です。

形式はpow(base, exp)で、戻り値はdoubleです。

たとえばpow(2.0, 3.0)は8.0を返します。

C言語では^はべき乗ではなくビットXORなので、必ずpowを使います。

#include <math.h> の書き方

powを使うには#include <math.h>を記述します。

出力表示には#include <stdio.h>も必要です。

C言語
// powの最小例: 2の10乗を表示
#include <stdio.h>
#include <math.h>

int main(void) {
    double result = pow(2.0, 10.0); // 2^10
    printf("2^10 = %.0f\n", result);
    return 0;
}
実行結果
2^10 = 1024

コンパイル方法

GCCやClangではリンク時に-lmが必要です。

WindowsのMSVCでは不要です。

Shell
# GCC/Clang (Linux, macOSなど): -lmは末尾に付けるのが安全
gcc main.c -o pow_sample -lm
./pow_sample

# Clangの例
clang main.c -o pow_sample -lm
./pow_sample

# Windows (MSVC)
cl /W4 /EHsc main.c
.\main.exe

引数と戻り値

基本プロトタイプは次の通りです。

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

powxy乗を返します。

戻り値は浮動小数点であり、誤差やオーバーフローNaNInfinityが起きる可能性があります。

負の底に小数指数などの定義域外ではNaNになります。

以下に簡単な対応表を示します。

関数引数の型戻り値の型主な用途
powdouble, doubledouble一般的な倍精度演算
powffloat, floatfloat単精度で統一したい場合
powllong double, long doublelong double高精度が必要な場合

基本の呼び出し(pow(base, exp))

最も基本的な使い方は、pow(底, 指数)です。

指数に負数を渡せば逆数の計算になります。

C言語
#include <stdio.h>
#include <math.h>

int main(void) {
    double a = pow(2.0, 5.0);    // 2^5 = 32
    double b = pow(2.0, -3.0);   // 2^-3 = 1/8 = 0.125
    double c = pow(9.0, 0.5);    // 9^(1/2) = sqrt(9) = 3

    printf("2^5   = %.0f\n", a);
    printf("2^-3  = %.3f\n", b);
    printf("9^0.5 = %.1f\n", c);
    return 0;
}
実行結果
2^5   = 32
2^-3  = 0.125
9^0.5 = 3.0

powの使い方と型の扱い

整数リテラルもdoubleに変換

powdoubleを取るため、pow(2, 10)のように整数リテラルを書いても、呼び出し時にdoubleへ自動変換されます。

可読性のため2.010.0のように小数点を付けることもあります。

C言語
#include <stdio.h>
#include <math.h>

int main(void) {
    // いずれも内部的にはdouble演算です
    double x = pow(2, 10);     // intリテラル -> doubleへ変換
    double y = pow(2.0, 10.0); // こちらは明示的にdouble

    printf("pow(2, 10)   = %.0f\n", x);
    printf("pow(2.0, 10) = %.0f\n", y);
    return 0;
}
実行結果
pow(2, 10)   = 1024
pow(2.0, 10) = 1024

結果をintにする

戻り値はdoubleなので、整数が欲しい場合は型変換が必要です。

ただし単純キャストは小数点以下を切り捨てます。

丸めたい場合はround/lround/llroundを使います。

また、結果が整数型の範囲に収まるか事前に確認してください。

C言語
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <limits.h>

int main(void) {
    // 典型例: 2^10 は厳密に1024なので問題なし
    double d1 = pow(2.0, 10.0);
    int i1 = (int)d1; // 小数部分がなければそのまま
    printf("2^10 -> (int)%d\n", i1);

    // 注意例: 8^(1/3) は理論上2だが、powは1.999999...になる可能性
    double d2 = pow(8.0, 1.0/3.0);
    int i2_trunc = (int)d2;          // 切り捨て -> 1 になるかもしれない
    long long i2_round = llround(d2); // 最も近い整数へ丸め -> 2 になることを期待
    printf("8^(1/3) = %.15f, (int) = %d, llround = %lld\n", d2, i2_trunc, i2_round);

    // 安全のための範囲チェック: 丸める前に範囲を確認
    double big = pow(10.0, 12.0); // 1e12 は long long に収まる
    if (isfinite(big) && fabsl(big) <= (long double)LLONG_MAX) {
        long long safely = llround(big);
        printf("1e12 を llround -> %lld\n", safely);
    } else {
        printf("結果が整数型に収まりません\n");
    }
    return 0;
}
実行結果
2^10 -> (int)1024
8^(1/3) = 1.999999999999999, (int) = 1, llround = 2
1e12 を llround -> 1000000000000
ポイント

lroundllroundは範囲外に丸めようとすると未定義動作になる可能性があります。

比較で範囲チェックをしてから使うと安全です。

大きな指数の限界

倍精度double約1e308までしか表現できません。

例えばpow(10.0, 400.0)オーバーフロー+Infになります。

逆に非常に小さい値はアンダーフロー0になります。

C言語
#include <stdio.h>
#include <math.h>

int main(void) {
    double of = pow(10.0, 400.0);   // オーバーフロー -> +Inf
    double uf = pow(10.0, -400.0);  // アンダーフロー -> 0
    double e2 = pow(2.0, 1024.0);   // 2^1024 も通常は +Inf

    printf("10^400 = %f, isinf = %d\n", of, isinf(of) != 0);
    printf("10^-400 = %.1e\n", uf);
    printf("2^1024 = %f, isinf = %d\n", e2, isinf(e2) != 0);
    return 0;
}
実行結果
10^400 = inf, isinf = 1
10^-400 = 0.0e+00
2^1024 = inf, isinf = 1

powf/powlの使い分け

型を統一すると精度と速度の両面で安定します。

float中心ならpowf、long double中心ならpowlを選び、混在しないようにします。

C言語
#include <stdio.h>
#include <math.h>

int main(void) {
    float xf = 1.5f, yf = 3.0f;
    float rf = powf(xf, yf); // 単精度

    double xd = 1.5, yd = 3.0;
    double rd = pow(xd, yd); // 倍精度

    long double xl = 1.5L, yl = 3.0L;
    long double rl = powl(xl, yl); // 拡張精度

    printf("powf(1.5f, 3.0f) = %.6f\n", rf);
    printf("pow(1.5,  3.0)   = %.6f\n", rd);
    printf("powl(1.5L, 3.0L) = %.6Lf\n", rl);
    return 0;
}
実行結果
powf(1.5f, 3.0f) = 3.375000
pow(1.5,  3.0)   = 3.375000
powl(1.5L, 3.0L) = 3.375000

powの注意点とよくある誤り

^はべき乗ではない

^演算子はビットXORです。

べき乗で使うと間違った結果になります。

C言語
#include <stdio.h>

int main(void) {
    int a = 2 ^ 3; // 2 XOR 3 = 1
    printf("2 ^ 3 = %d (これはべき乗ではありません)\n", a);
    return 0;
}
実行結果
2 ^ 3 = 1 (これはべき乗ではありません)

負の底と小数の指数

負の底に非整数の指数は実数の範囲で定義できず、powNaNになります。

実数の解が欲しい場合でもpow(-8.0, 1.0/3.0)のような表現は移植性がありません

立方根cbrtを使うと安全です。

C言語
#include <stdio.h>
#include <math.h>

int main(void) {
    double r1 = pow(-8.0, 1.0/3.0); // 実装によってNaN
    double r2 = cbrt(-8.0);         // 立方根: -2 を返す

    printf("pow(-8, 1/3) = %f, isnan = %d\n", r1, isnan(r1) != 0);
    printf("cbrt(-8)     = %f\n", r2);
    return 0;
}
実行結果
pow(-8, 1/3) = nan, isnan = 1
cbrt(-8)     = -2.000000

整数の指数であれば負の底でも問題ありません。

例えばpow(-2.0, 3.0)は-8を返します。

0の負の指数は不可

pow(0.0, 負の数)定義域外で、+Infになるのが一般的です。

除算による無限大のような扱いになります。

C言語
#include <stdio.h>
#include <math.h>

int main(void) {
    double r = pow(0.0, -1.0); // 1 / 0.0 と同様の扱い
    printf("0^-1 = %f, isinf = %d\n", r, isinf(r) != 0);
    return 0;
}
実行結果
0^-1 = inf, isinf = 1

丸め誤差で整数にならない

浮動小数点では「理論上は整数」でもぴったり表現できないことがあります。

pow(8.0, 1.0/3.0)は2に近い値でも、(int)で切り捨てると1になる場合があります。

整数にしたいなら丸め関数を使うか、整数べきは整数演算で計算するのが安全です。

C言語
#include <stdio.h>
#include <math.h>

int main(void) {
    double v = pow(27.0, 1.0/3.0); // 3に近いが 2.999999... になる可能性
    int bad = (int)v;              // 切り捨て -> 2 になるかも
    int good = (int)lround(v);     // 丸め -> 3

    printf("27^(1/3) = %.15f, (int) = %d, lround = %d\n", v, bad, good);
    return 0;
}
実行結果
27^(1/3) = 3.000000000000000, (int) = 3, lround = 3
注意

実行環境によっては上の例で誤差が現れず、偶然きれいな3.0になることもあります。

誤差が出る可能性を常に考えることが大切です。

powサンプル集

2の10乗(pow(2, 10))

最も基本的な整数べきの例です。

C言語
#include <stdio.h>
#include <math.h>

int main(void) {
    printf("2^10 = %.0f\n", pow(2.0, 10.0));
    return 0;
}
実行結果
2^10 = 1024

小数のべき乗(pow(1.5, 3))

小数の底と整数指数の組み合わせです。

C言語
#include <stdio.h>
#include <math.h>

int main(void) {
    double ans = pow(1.5, 3.0); // 1.5^3 = 3.375
    printf("1.5^3 = %.3f\n", ans);
    return 0;
}
実行結果
1.5^3 = 3.375

結果をintにキャスト

整数値が期待できる場合でも、丸めと範囲に注意します。

C言語
#include <stdio.h>
#include <math.h>
#include <limits.h>

int main(void) {
    double val = pow(5.0, 3.0); // 125
    int a = (int)val;           // 小数なし -> そのまま125
    int b = (int)lround(val);   // 丸めても125

    printf("5^3 = %f, (int) = %d, lround = %d\n", val, a, b);

    // 範囲に注意 (例: 2^40 はintに収まらない)
    double big = pow(2.0, 40.0); // 約1兆
    printf("2^40 = %.0f -> intにキャストするとオーバーフローの危険\n", big);
    return 0;
}
実行結果
5^3 = 125.000000, (int) = 125, lround = 125
2^40 = 1099511627776 -> intにキャストするとオーバーフローの危険

関数内でpowを使う

たとえば複利計算など、関数内でpowを用いると見通しが良くなります。

C言語
#include <stdio.h>
#include <math.h>

// 複利計算: 元本P, 年利r, 年数n -> P * (1 + r)^n
double compound(double principal, double rate, int years) {
    return principal * pow(1.0 + rate, (double)years);
}

int main(void) {
    double p = 100000.0; // 元本
    double r = 0.03;     // 年利3%
    int    n = 5;        // 5年

    double future = compound(p, r, n);
    printf("元本%.0f円が年利%.1f%%で%d年後: %.2f円\n", p, r*100, n, future);
    return 0;
}
実行結果
元本100000円が年利3.0%で5年後: 115927.41円

まとめ

C言語でべき乗はpowを使って計算します。

ヘッダはmath.hで、GCCやClangではリンク時に-lmが必要です。

戻り値は浮動小数点であり、丸め誤差オーバーフロー/アンダーフローNaNの可能性を常に考慮します。

負の底に小数指数は避け、必要ならcbrtsqrtなどの専用関数を使いましょう。

整数が欲しい場合は、単純キャストではなく丸め関数と範囲チェックを組み合わせると安全です。

最後に、^はべき乗ではない点を忘れず、powfpowlも含めて型を統一して使うことで、予期せぬ不具合を避けられます。

この記事を書いた人
エーテリア編集部
エーテリア編集部

プログラミングの基礎をしっかり学びたい方向けに、C言語の基本文法から解説しています。ポインタやメモリ管理も少しずつ理解できるよう工夫しています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!