言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

C言語辞典

  1. トップページ
  2. C言語辞典
  3. fmod() / modf() / frexp() / ldexp()

fmod() / modf() / frexp() / ldexp()

対応: C89(1989)

浮動小数点数を細かく操作するための関数です。『<math.h>』に定義されており、余剰計算・整数部と小数部の分離・仮数と指数への分解など、低レベルな浮動小数点演算に使われます。コンパイル時に『-lm』リンクオプションが必要な場合があります。

構文

// x を y で割った浮動小数点数の余りを返します(符号は x に合わせます)。
double fmod(double x, double y);

// x の整数部と小数部を分離します。整数部を *iptr に格納し、小数部を返します。
double modf(double x, double *iptr);

// x を 仮数 × 2^exp の形に分解します。仮数を戻り値として返し、指数を *exp に格納します。
// 仮数の絶対値は [0.5, 1.0) の範囲です。
double frexp(double x, int *exp);

// x × 2^exp を計算します(frexp の逆操作)。
double ldexp(double x, int exp);

関数一覧

関数概要
fmod()浮動小数点数の除算余りを返します。整数の『%』演算子の浮動小数点版です。
modf()浮動小数点数を整数部と小数部に分割します。両方とも double 型で得られます。
frexp()浮動小数点数を仮数部と指数部に分解します。IEEE 754 の内部表現を取り出す低レベル操作です。
ldexp()仮数部と指数部から浮動小数点数を合成します。frexp() の逆操作です。

サンプルコード

sample_fmod_modf_frexp_ldexp.c
#include <stdio.h>
#include <math.h>

int main(void) {
    /* fmod で浮動小数点の余りを求めます(% は整数専用です)。 */
    printf("fmod(5.7, 2.0) = %.1f\n", fmod(5.7, 2.0));
    printf("fmod(-5.7, 2.0) = %.1f\n", fmod(-5.7, 2.0)); /* 被除数の符号になります。 */

    /* 角度を 0°〜360° の範囲に正規化します。 */
    double angle = 730.5;
    double normalized = fmod(angle, 360.0);
    printf("%.1f° → 正規化後: %.1f°\n", angle, normalized);

    /* modf で整数部と小数部を分離します。 */
    double int_part;
    double frac_part = modf(3.75, &int_part);
    printf("3.75 の整数部: %.1f、小数部: %.2f\n", int_part, frac_part);

    double neg_frac = modf(-2.3, &int_part);
    printf("-2.3 の整数部: %.1f、小数部: %.1f\n", int_part, neg_frac);

    /* frexp で仮数と指数に分解します。8.0 = 0.5 × 2^4 */
    int exp;
    double mantissa = frexp(8.0, &exp);
    printf("frexp(8.0): 仮数 = %.4f、指数 = %d\n", mantissa, exp);

    /* ldexp で frexp の逆操作をします。 */
    double restored = ldexp(mantissa, exp);
    printf("ldexp(%.4f, %d) = %.1f\n", mantissa, exp, restored);

    return 0;
}

コンパイルして実行すると次のようになります。

gcc fmod_modf_frexp_ldexp.c -o fmod_modf_frexp_ldexp -lm
./fmod_modf_frexp_ldexp
fmod(5.7, 2.0) = 1.7
fmod(-5.7, 2.0) = -1.7
730.5° → 正規化後: 10.5°
3.75 の整数部: 3.0、小数部: 0.75
-2.3 の整数部: -2.0、小数部: -0.3
frexp(8.0): 仮数 = 0.5000、指数 = 4
ldexp(0.5000, 4) = 8.0

よくあるミス

よくあるミス: fmod の除数に 0 を渡す

fmod(x, 0.0) は NaN(非数)を返します。除数がゼロでないことを事前に確認してください。

fmod_zero_ng.c
#include <stdio.h>
#include <math.h>

int main(void) {
    /* NG: 除数が 0 だと NaN になります。 */
    double ng = fmod(5.0, 0.0);
    printf("fmod(5.0, 0.0) = %f\n", ng); /* nan と出力されます。 */

    /* OK: 0 でないことを確認してから呼び出します。 */
    double divisor = 2.0;
    if (divisor != 0.0) {
        double result = fmod(5.0, divisor);
        printf("fmod(5.0, 2.0) = %.1f\n", result); /* 1.0 */
    } else {
        printf("除数が 0 です。\n");
    }

    /* NaN かどうかは isnan() で確認できます(math.h)。 */
    if (isnan(ng)) {
        printf("fmod(5.0, 0.0) は NaN です。\n");
    }

    return 0;
}

修正後は次の通りです。

gcc fmod_zero_ng.c -o fmod_zero_ng -lm
./fmod_zero_ng
fmod(5.0, 0.0) = nan
fmod(5.0, 2.0) = 1.0
fmod(5.0, 0.0) は NaN です。

概要

整数型の『%』演算子は浮動小数点数には使えません。浮動小数点数の余りを求める場合は必ず『fmod()』を使用してください。ゲーム開発での角度正規化や周期的な計算など、浮動小数点数の折り返し処理によく使われます。

『modf()』は整数部も double 型(小数部がゼロ)として返します。整数の floor() とは異なり、負の値でも整数部の符号が元の数と一致します(例:-2.3 の整数部は -2.0)。単に小数を切り捨てたい場合は『floor()』が適しています。

『frexp()』と『ldexp()』は IEEE 754 の浮動小数点数の内部表現(仮数部と指数部)を直接操作します。一般的なアプリケーションではあまり使いませんが、数値計算ライブラリや高精度演算の実装では重要な役割を果たします。

fmod(x, 0.0) の結果は未定義(NaN)になります。除数が 0 でないことを事前に確認してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。