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.
#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:
sqrt(16.0) = 4.0000
pow(2.0, 10.0) = 1024.0
fabs(-3.14) = 3.14
ceil(3.25) = 4
floor(3.25) = 3Mari kita telaah baris-baris kode di atas:
- Baris 7 (
sqrt(x)):sqrtmenerimadoubledan mengembalikandouble. Untuk tipefloat, gunakansqrtf; untuklong double, gunakansqrtl. Konvensi sufiksf/lini berlaku untuk semua fungsi di<math.h>. - Baris 9 (
pow(2.0, 10.0)):pow(x, y)menghitungx^y. Bila hasil di luar jangkauandouble(misalpow(10.0, 1000.0)), terjadi range error danerrnodiatur keERANGE. - Baris 12 (
fabs(-3.14)): nilai absolut untukdouble. Jangan tertukar denganabsdi<stdlib.h>yang hanya menerimaint—bila Anda memakaiabs(-3.14), kompiler mungkin membulatkan keintlebih dulu sehingga hasilnya3, bukan3.14. - Baris 15-16 (
ceil,floor): kedua fungsi mengembalikandouble, bukanint. Untuk kasus di mana Anda butuhint, tambahkan cast eksplisit:(int)floor(y). Atau gunakanlround/llroundyang membulatkan kelong/long longterdekat.
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).
#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:
sin(pi/4) = 0.707107
cos(pi/4) = 0.707107
log(e) = 1.000000
exp(1.0) = 2.718282
log10(1000) = 3.0Nilai 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.
#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:
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 = infFungsi 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.