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 #

KonstantaNilaiDeskripsi
pi3.14159…π
e2.71828…Bilangan Euler
sqrt21.41421…√2
sqrt1_20.70710…1/√2
ln20.69314…ln(2)
ln102.30258…ln(10)
log2e1.44269…log₂(e)
log10e0.43429…log₁₀(e)

Fungsi #

FungsiKeterangan
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 #

KelasKeterangan
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 sempurna0.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 →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact