Header <math.h> menyediakan fungsi matematika untuk tipe floating-point: trigonometri (sin, cos, tan), logaritma (log, log10, log2), eksponensial (exp), pangkat (pow), akar (sqrt, cbrt), pembulatan (ceil, floor, round), dan nilai absolut (fabs). Berbeda dengan abs di <stdlib.h> yang bekerja pada int, fabs bekerja pada double. Karena fungsi-fungsi ini dipisahkan ke pustaka matematika terpisah (libm), kita perlu menambahkan flag -lm saat linking. Pada chapter ini kita akan meninjau fungsi inti <math.h>, penanganan domain error, dan special value seperti NaN dan Infinity.

Fungsi Dasar: sqrt, pow, fabs, ceil, floor #

Fungsi sqrt menghitung akar pangkat dua, pow(x, y) menghitung x pangkat y. Fungsi fabs mengembalikan nilai absolut dari double (analog abs untuk int). Untuk pembulatan, ceil membulatkan ke atas dan floor membulatkan ke bawah, keduanya mengembalikan double—bukan int.

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

int main(void) {
    /* sqrt dan pow */
    double x = 16.0;
    printf("sqrt(%.1f) = %.4f\n", x, sqrt(x));
    printf("pow(2.0, 10.0) = %.1f\n", pow(2.0, 10.0));

    /* fabs: nilai absolut floating point */
    printf("fabs(-3.14) = %.2f\n", fabs(-3.14));

    /* Pembulatan: ceil dan floor */
    double y = 3.25;
    printf("ceil(%.2f) = %.0f\n", y, ceil(y));
    printf("floor(%.2f) = %.0f\n", y, floor(y));

    return 0;
}

Output yang Dihasilkan:

text
sqrt(16.0) = 4.0000
pow(2.0, 10.0) = 1024.0
fabs(-3.14) = 3.14
ceil(3.25) = 4
floor(3.25) = 3

Mari kita telaah baris-baris kode di atas:

  1. Baris 7 (sqrt(x)): sqrt menerima double dan mengembalikan double. Untuk tipe float, gunakan sqrtf; untuk long double, gunakan sqrtl. Konvensi sufiks f/l ini berlaku untuk semua fungsi di <math.h>.
  2. Baris 9 (pow(2.0, 10.0)): pow(x, y) menghitung x^y. Bila hasil di luar jangkauan double (misal pow(10.0, 1000.0)), terjadi range error dan errno diatur ke ERANGE.
  3. Baris 12 (fabs(-3.14)): nilai absolut untuk double. Jangan tertukar dengan abs di <stdlib.h> yang hanya menerima int—bila Anda memakai abs(-3.14), kompiler mungkin membulatkan ke int lebih dulu sehingga hasilnya 3, bukan 3.14.
  4. Baris 15-16 (ceil, floor): kedua fungsi mengembalikan double, bukan int. Untuk kasus di mana Anda butuh int, tambahkan cast eksplisit: (int)floor(y). Atau gunakan lround/llround yang membulatkan ke long/long long terdekat.

Trigonometri dan Logaritma #

Fungsi trigonometri sin, cos, tan menerima argumen dalam radian, bukan derajat. Untuk mengkonversi derajat ke radian, kalikan dengan π/180. Fungsi log menghitung logaritma natural (basis e), log10 basis 10, dan log2 basis 2. Kebalikannya, exp(x) menghitung e^x.

Konstanta M_PI dan M_E sering tersedia di sistem POSIX/GNU, tetapi bukan bagian dari ISO/IEC 9899 standar—-std=c11 ketat tidak mengeksposnya. Untuk portabilitas, kita dapat menghitung π lewat ekspresi 4.0 * atan(1.0) dan e lewat exp(1.0).

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

int main(void) {
    /* Hitung pi dan e lewat ekspresi standar C (M_PI/M_E adalah ekstensi POSIX) */
    const double pi = 4.0 * atan(1.0);    /* pi */
    const double e  = exp(1.0);            /* konstanta Euler */

    /* sin, cos (argumen dalam radian!) */
    double sudut = pi / 4;   /* 45 derajat */
    printf("sin(pi/4) = %.6f\n", sin(sudut));
    printf("cos(pi/4) = %.6f\n", cos(sudut));

    /* log (basis e) dan exp */
    printf("log(e) = %.6f\n", log(e));
    printf("exp(1.0) = %.6f\n", exp(1.0));

    /* log10 (basis 10) */
    printf("log10(1000) = %.1f\n", log10(1000.0));

    return 0;
}

Output yang Dihasilkan:

text
sin(pi/4) = 0.707107
cos(pi/4) = 0.707107
log(e) = 1.000000
exp(1.0) = 2.718282
log10(1000) = 3.0

Nilai sin(pi/4) dan cos(pi/4) sama yaitu sekitar 0.7071—sesuai fakta geometris bahwa sin(45°) = cos(45°) = √2/2. Pernyataan log(e) = 1 menegaskan bahwa logaritma natural basis e dari e sendiri adalah 1. Untuk menghitung logaritma basis b dari x dengan basis arbitrer, gunakan identitas log_b(x) = log(x) / log(b).

Penanganan Error: NaN dan Infinity #

Bila input di luar domain fungsi (misal sqrt(-1.0)), <math.h> mengembalikan nilai NaN (Not-a-Number) dan menetapkan errno = EDOM. Bila hasil terlalu besar (misal exp(1000.0)), fungsi mengembalikan HUGE_VAL (Infinity) dan menetapkan errno = ERANGE. Makro isnan(x) dan isinf(x) memeriksa apakah nilai adalah NaN atau Infinity.

c
#include <stdio.h>
#include <math.h>
#include <errno.h>
#include <string.h>

int main(void) {
    /* Domain error: sqrt dari bilangan negatif */
    errno = 0;
    double r = sqrt(-1.0);
    printf("sqrt(-1) = %f, errno=%d (%s)\n", r, errno, strerror(errno));

    /* Range error: exp dari angka terlalu besar */
    errno = 0;
    double big = exp(1000.0);
    printf("exp(1000) = %f, errno=%d (%s)\n", big, errno, strerror(errno));

    /* NaN dan infinity */
    printf("\nisnan(sqrt(-1)) = %d\n", isnan(sqrt(-1.0)));
    printf("isinf(exp(1000)) = %d\n", isinf(exp(1000.0)));
    printf("HUGE_VAL = %f\n", HUGE_VAL);

    return 0;
}

Output yang Dihasilkan:

text
sqrt(-1) = -nan, errno=33 (Numerical argument out of domain)
exp(1000) = inf, errno=34 (Numerical result out of range)

isnan(sqrt(-1)) = 1
isinf(exp(1000)) = 1
HUGE_VAL = inf

Fungsi sqrt(-1.0) mengembalikan NaN (ditampilkan sebagai -nan atau nan tergantung runtime) dan errno diatur ke EDOM (kode 33 di sistem ini). Fungsi exp(1000.0) mengembalikan inf dan errno = ERANGE (kode 34). Tepat sebelum memanggil fungsi yang mungkin error, kita wajib me-reset errno = 0—sebaliknya, errno berisi nilai sisa dari kegagalan sebelumnya dan akan menyesatkan. Makro isnan dan isinf memberi cara portabel untuk memeriksa special value tanpa harus membandingkan langsung dengan NAN atau INFINITY.