Math
#
dart:math adalah library bawaan Dart untuk operasi matematika — konstanta seperti pi dan e, fungsi trigonometri, logaritma, akar kuadrat, nilai minimum/maksimum, serta pembangkit angka acak. Untuk operasi matematika yang lebih kompleks (matriks, statistik, bilangan kompleks), gunakan package math dari pub.dev. Artikel ini membahas seluruh dart:math secara mendalam beserta contoh penerapan nyata.
Import
#
import 'dart:math';
// Semua fungsi dan konstanta tersedia langsung setelah import
print(pi); // 3.141592653589793
print(e); // 2.718281828459045
print(sqrt(2)); // 1.4142135623730951
Konstanta Matematika
#
import 'dart:math';
// Konstanta dasar
print(pi); // π = 3.141592653589793 — rasio keliling dan diameter lingkaran
print(e); // e = 2.718281828459045 — basis logaritma natural
print(sqrt2); // √2 = 1.4142135623730951 — akar kuadrat dari 2
print(sqrt1_2); // 1/√2 = 0.7071067811865476 — akar kuadrat dari 1/2
print(ln2); // ln(2) = 0.6931471805599453 — logaritma natural dari 2
print(ln10); // ln(10) = 2.302585092994046 — logaritma natural dari 10
print(log2e); // log₂(e) = 1.4426950408889634 — logaritma basis 2 dari e
print(log10e); // log₁₀(e) = 0.4342944819032518 — logaritma basis 10 dari e
// Konstanta derived yang berguna (tidak tersedia langsung, hitung manual)
final dua_pi = 2 * pi; // 2π — satu putaran penuh dalam radian
final pi_per_dua = pi / 2; // π/2 — 90 derajat dalam radian
final pi_per_empat = pi / 4; // π/4 — 45 derajat dalam radian
final phi = (1 + sqrt(5)) / 2; // φ ≈ 1.618... — golden ratio
Fungsi Dasar
#
min dan max
#
import 'dart:math';
// min — nilai terkecil dari dua angka
print(min(3, 7)); // 3
print(min(-5, -2)); // -5
print(min(3.14, 2.71)); // 2.71
print(min(double.infinity, 100.0)); // 100.0
// max — nilai terbesar dari dua angka
print(max(3, 7)); // 7
print(max(-5, -2)); // -2
// Clamp — batasi nilai dalam rentang (bukan dari dart:math tapi method num)
double nilai = 150.0;
print(nilai.clamp(0, 100)); // 100.0 — dibatasi maksimal 100
print((-5).clamp(0, 100)); // 0 — dibatasi minimal 0
print(75.clamp(0, 100)); // 75 — dalam rentang, tidak berubah
// Min/Max dari list — gunakan reduce atau collection
List<int> angka = [3, 1, 4, 1, 5, 9, 2, 6];
int minimum = angka.reduce(min); // 1
int maksimum = angka.reduce(max); // 9
// Atau dengan package collection
import 'package:collection/collection.dart';
print(angka.min); // 1
print(angka.max); // 9
pow — Pemangkatan
#
import 'dart:math';
// pow(x, y) — x pangkat y, mengembalikan num
print(pow(2, 10)); // 1024 — 2^10
print(pow(2, -1)); // 0.5 — 2^(-1) = 1/2
print(pow(4, 0.5)); // 2.0 — √4 (akar kuadrat = pangkat 1/2)
print(pow(8, 1/3)); // 2.0 — ∛8 (akar kubik = pangkat 1/3)
print(pow(10, 3)); // 1000 — 10^3
print(pow(-2, 3)); // -8 — (-2)^3
// Untuk pangkat integer, operator ~/ atau toInt() setelah pow
int kekuatan2 = pow(2, 8).toInt(); // 256
sqrt — Akar Kuadrat
#
import 'dart:math';
print(sqrt(4)); // 2.0
print(sqrt(2)); // 1.4142135623730951
print(sqrt(9)); // 3.0
print(sqrt(0)); // 0.0
print(sqrt(-1)); // NaN — akar kuadrat bilangan negatif
// Akar n-th menggunakan pow
double akarKubik(double x) => pow(x, 1/3).toDouble();
print(akarKubik(27)); // 3.0
// Jarak Euclidean antara dua titik
double jarak(double x1, double y1, double x2, double y2) {
return sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
}
print(jarak(0, 0, 3, 4)); // 5.0 — segitiga 3-4-5
Trigonometri
#
Semua fungsi trigonometri dart:math bekerja dalam radian, bukan derajat:
import 'dart:math';
// Konversi antara derajat dan radian
double toRadian(double derajat) => derajat * pi / 180;
double toDegree(double radian) => radian * 180 / pi;
print(toRadian(90)); // 1.5707963... (π/2)
print(toDegree(pi)); // 180.0
// Fungsi trigonometri dasar
// sin, cos, tan — semua menerima radian
print(sin(0)); // 0.0
print(sin(pi / 2)); // 1.0 — sin(90°)
print(sin(pi)); // 1.2246467991473532e-16 (≈ 0, floating point)
print(cos(0)); // 1.0
print(cos(pi)); // -1.0 — cos(180°)
print(cos(pi / 2)); // 6.123233995736766e-17 (≈ 0)
print(tan(pi / 4)); // 1.0 (≈ 1) — tan(45°)
print(tan(toRadian(45))); // 0.9999999999999999 ≈ 1
// Fungsi invers (arc)
print(asin(1)); // π/2 = 1.5707... — arcsin(1) = 90°
print(acos(1)); // 0.0 — arccos(1) = 0°
print(atan(1)); // π/4 = 0.7853... — arctan(1) = 45°
// atan2 — sudut dari titik (y, x) — lebih aman dari atan(y/x)
print(atan2(1, 1)); // π/4 = 0.7853... — titik (1,1) = 45°
print(atan2(0, -1)); // π = 3.1415... — titik (-1,0) = 180°
print(atan2(-1, 0)); // -π/2 — titik (0,-1) = -90°
Aplikasi Trigonometri
#
import 'dart:math';
// Hitung koordinat titik pada lingkaran
// x = r * cos(θ), y = r * sin(θ)
List<(double, double)> titikPadaLingkaran(double radius, int n) {
return List.generate(n, (i) {
final sudut = 2 * pi * i / n;
return (radius * cos(sudut), radius * sin(sudut));
});
}
// 6 titik pada lingkaran jari-jari 10 (hexagon)
final titik = titikPadaLingkaran(10, 6);
for (final (x, y) in titik) {
print('(${x.toStringAsFixed(2)}, ${y.toStringAsFixed(2)})');
}
// Haversine formula — jarak antara dua koordinat GPS
double haversine(
double lat1, double lon1,
double lat2, double lon2,
) {
const radiusBumi = 6371.0; // km
final dLat = toRadian(lat2 - lat1);
final dLon = toRadian(lon2 - lon1);
final a = sin(dLat / 2) * sin(dLat / 2) +
cos(toRadian(lat1)) * cos(toRadian(lat2)) *
sin(dLon / 2) * sin(dLon / 2);
final c = 2 * atan2(sqrt(a), sqrt(1 - a));
return radiusBumi * c;
}
// Jarak Jakarta → Surabaya
double jarak = haversine(-6.2088, 106.8456, -7.2459, 112.7378);
print('Jarak: ${jarak.toStringAsFixed(0)} km'); // ~664 km
Logaritma dan Eksponensial
#
import 'dart:math';
// log — logaritma natural (basis e)
print(log(1)); // 0.0 — ln(1) = 0
print(log(e)); // 1.0 — ln(e) = 1
print(log(e * e)); // 2.0 — ln(e²) = 2
print(log(10)); // 2.302585... — ln(10)
// Logaritma basis lain — gunakan change of base formula: log_b(x) = ln(x) / ln(b)
double logBasis(double x, double basis) => log(x) / log(basis);
double log2(double x) => log(x) / ln2; // logaritma basis 2
double log10(double x) => log(x) / ln10; // logaritma basis 10
print(log2(8)); // 3.0 — 2^3 = 8
print(log10(100)); // 2.0 — 10^2 = 100
print(logBasis(27, 3)); // 3.0 — 3^3 = 27
// Eksponensial — e^x
double exp(double x) => pow(e, x).toDouble();
// atau lebih akurat: tidak ada exp() di dart:math, gunakan pow(e, x)
print(pow(e, 0)); // 1.0 — e^0
print(pow(e, 1)); // 2.718281... — e^1 = e
print(pow(e, 2)); // 7.389056... — e^2
Random — Angka Acak
#
import 'dart:math';
// Random standar — pseudo-random, tidak kriptografis
final random = Random();
// Bilangan bulat acak [0, max)
print(random.nextInt(10)); // 0 sampai 9
print(random.nextInt(100)); // 0 sampai 99
// Rentang [min, max]
int rentang(int min, int max) => min + random.nextInt(max - min + 1);
print(rentang(1, 6)); // simulasi dadu — 1 sampai 6
// Double acak [0.0, 1.0)
print(random.nextDouble()); // 0.0 sampai 0.9999...
// Double dalam rentang [min, max)
double doubleRentang(double min, double max) {
return min + random.nextDouble() * (max - min);
}
print(doubleRentang(1.5, 2.5)); // antara 1.5 dan 2.5
// Boolean acak
print(random.nextBool()); // true atau false dengan probabilitas 50%
// Seed — untuk hasil yang reproducible (berguna untuk testing)
final seeded = Random(42);
print(seeded.nextInt(100)); // selalu sama untuk seed yang sama
print(seeded.nextInt(100)); // urutan selalu sama
Random.secure — Kriptografis
#
import 'dart:math';
// Random.secure — menggunakan sumber entropy OS, cocok untuk kriptografi
final secureRandom = Random.secure();
// Generate token acak yang aman (untuk session ID, API key, dll.)
String generateToken(int panjang) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
return List.generate(
panjang,
(_) => chars[secureRandom.nextInt(chars.length)],
).join();
}
print(generateToken(32)); // token 32 karakter acak yang aman
// Generate bytes acak (untuk salt, nonce, dll.)
List<int> generateSalt(int ukuran) {
return List.generate(ukuran, (_) => secureRandom.nextInt(256));
}
final salt = generateSalt(16);
print(salt); // [45, 127, 23, ...] — 16 bytes acak
// UUID v4 sederhana menggunakan Random.secure
String generateUUID() {
final bytes = List.generate(16, (_) => secureRandom.nextInt(256));
bytes[6] = (bytes[6] & 0x0f) | 0x40; // versi 4
bytes[8] = (bytes[8] & 0x3f) | 0x80; // varian RFC 4122
final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
return '${hex.substring(0,8)}-${hex.substring(8,12)}-'
'${hex.substring(12,16)}-${hex.substring(16,20)}-${hex.substring(20)}';
}
print(generateUUID()); // contoh: '550e8400-e29b-41d4-a716-446655440000'
// ANTI-PATTERN: menggunakan Random() biasa untuk kebutuhan keamanan
final random = Random();
final sessionId = random.nextInt(1000000).toString(); // ✗ mudah diprediksi!
// BENAR: Random.secure() untuk token yang butuh keamanan
final secureRandom = Random.secure();
final sessionId = generateToken(32); // ✓ tidak bisa diprediksi
Presisi Floating-Point — Gotcha yang Perlu Diketahui
#
import 'dart:math';
// Floating-point representation tidak sempurna
print(0.1 + 0.2); // 0.30000000000000004 — bukan 0.3!
print(0.1 + 0.2 == 0.3); // false!
// Nilai spesial double
print(double.infinity); // Infinity
print(double.negativeInfinity); // -Infinity
print(double.nan); // NaN
print(double.maxFinite); // 1.7976931348623157e+308
print(double.minPositive); // 5e-324
// Cek nilai spesial
double nilai = 0 / 0;
print(nilai.isNaN); // true
print(nilai.isInfinite); // false
print(nilai.isFinite); // false
double inf = 1 / 0;
print(inf.isInfinite); // true
print(inf.isNaN); // false
// Perbandingan yang benar untuk floating-point
bool kiraKiraSama(double a, double b, {double toleransi = 1e-9}) {
return (a - b).abs() < toleransi;
}
print(kiraKiraSama(0.1 + 0.2, 0.3)); // true ✓
print(kiraKiraSama(sin(pi), 0.0)); // true ✓ (sin(π) bukan tepat 0)
// Pembulatan
print(3.7.round()); // 4 — pembulatan biasa
print(3.5.round()); // 4 — pembulatan ke atas untuk .5
print(3.7.ceil()); // 4 — pembulatan ke atas
print(3.2.ceil()); // 4 — pembulatan ke atas
print(3.7.floor()); // 3 — pembulatan ke bawah
print(3.7.truncate()); // 3 — potong desimal (arah nol)
print((-3.7).truncate()); // -3 — berbeda dari floor!
// Format desimal
double harga = 15750.5;
print(harga.toStringAsFixed(0)); // '15751'
print(harga.toStringAsFixed(2)); // '15750.50'
print(harga.toStringAsPrecision(4)); // '1.575e+4'
Aplikasi Praktis
#
Statistik Dasar
#
import 'dart:math';
class Statistik {
static double rerata(List<num> data) {
if (data.isEmpty) return 0;
return data.reduce((a, b) => a + b) / data.length;
}
static double variansPopulasi(List<num> data) {
final rata = rerata(data);
return data.map((x) => pow(x - rata, 2)).reduce((a, b) => a + b) / data.length;
}
static double standarDeviasi(List<num> data) => sqrt(variansPopulasi(data));
static num median(List<num> data) {
if (data.isEmpty) throw ArgumentError('Data kosong');
final sorted = List.of(data)..sort();
final mid = sorted.length ~/ 2;
return sorted.length.isOdd
? sorted[mid]
: (sorted[mid - 1] + sorted[mid]) / 2;
}
static num modus(List<num> data) {
final frekuensi = <num, int>{};
for (final x in data) frekuensi[x] = (frekuensi[x] ?? 0) + 1;
return frekuensi.entries.reduce((a, b) => a.value > b.value ? a : b).key;
}
}
void main() {
final data = [4, 8, 15, 16, 23, 42, 15, 8, 15];
print('Rerata: ${Statistik.rerata(data).toStringAsFixed(2)}');
print('Median: ${Statistik.median(data)}');
print('Modus: ${Statistik.modus(data)}');
print('Std Dev: ${Statistik.standarDeviasi(data).toStringAsFixed(2)}');
}
Operasi Bit dan Pangkat 2
#
import 'dart:math';
// Cek apakah angka adalah pangkat 2
bool adalahPangkat2(int n) => n > 0 && (n & (n - 1)) == 0;
// menggunakan bit manipulation — lebih efisien dari pow
print(adalahPangkat2(16)); // true
print(adalahPangkat2(12)); // false
// Bulatkan ke pangkat 2 terdekat
int bulatkanKePangkat2(int n) {
if (adalahPangkat2(n)) return n;
int hasil = 1;
while (hasil < n) hasil <<= 1;
return hasil;
}
print(bulatkanKePangkat2(100)); // 128
// Logaritma integer (floor log base 2)
int floorLog2(int n) {
assert(n > 0);
return (log(n) / ln2).floor();
}
print(floorLog2(8)); // 3 — 2^3 = 8
print(floorLog2(10)); // 3 — 2^3 = 8 ≤ 10 < 2^4 = 16
Referensi Lengkap dart:math
#
Konstanta
#
| Konstanta |
Nilai |
Deskripsi |
pi |
3.14159… |
π |
e |
2.71828… |
Bilangan Euler |
sqrt2 |
1.41421… |
√2 |
sqrt1_2 |
0.70710… |
1/√2 |
ln2 |
0.69314… |
ln(2) |
ln10 |
2.30258… |
ln(10) |
log2e |
1.44269… |
log₂(e) |
log10e |
0.43429… |
log₁₀(e) |
Fungsi
#
| Fungsi |
Keterangan |
min(a, b) |
Nilai minimum dari dua angka |
max(a, b) |
Nilai maksimum dari dua angka |
pow(x, y) |
x pangkat y |
sqrt(x) |
Akar kuadrat |
log(x) |
Logaritma natural |
sin(x) |
Sinus (radian) |
cos(x) |
Kosinus (radian) |
tan(x) |
Tangen (radian) |
asin(x) |
Arcus sinus |
acos(x) |
Arcus kosinus |
atan(x) |
Arcus tangen |
atan2(y, x) |
Sudut dari vektor (y, x) |
Kelas
#
| Kelas |
Keterangan |
Random() |
Pseudo-random number generator |
Random.secure() |
Kriptografis RNG menggunakan entropy OS |
Point<T> |
Representasi titik 2D dengan metode distanceTo |
Ringkasan
#
dart:math menyediakan konstanta pi, e, sqrt2, ln2, ln10 — tidak perlu mendefinisikan ulang di kode kamu.
- Semua fungsi trigonometri bekerja dalam radian — konversi dari/ke derajat dengan
radian = derajat * pi / 180.
atan2(y, x) lebih aman dari atan(y/x) — menangani kasus pembagian nol dan mengembalikan sudut yang benar di semua kuadran.
log(x) adalah logaritma natural — untuk basis lain gunakan change of base: log(x) / log(basis) atau log(x) / ln2 untuk basis 2.
Random() untuk simulation, Random.secure() untuk keamanan — token, session ID, salt, dan nonce harus menggunakan Random.secure() yang tidak bisa diprediksi.
- Floating-point tidak sempurna —
0.1 + 0.2 != 0.3. Gunakan fungsi perbandingan dengan toleransi (abs(a-b) < epsilon) untuk membandingkan nilai floating-point.
num.clamp(min, max) adalah method pada num, bukan fungsi di dart:math — berguna untuk membatasi nilai dalam rentang tertentu.
reduce(min) dan reduce(max) untuk mencari minimum/maksimum dari List — lebih idiomatis dari loop manual.
Random(seed) untuk hasil yang reproducible — berguna dalam test, simulasi, dan debugging yang butuh hasil deterministic.
- Untuk matematika yang lebih kompleks (matriks, FFT, statistik lanjut, bilangan kompleks), gunakan package
math atau ml_linalg dari pub.dev.
← Sebelumnya: IO
Berikutnya: Async →