Bilangan dan boolean

Bilangan bulat presisi arbitrer, aritmetika float, serta true dan false sebagai atom.

Daftar isi

Topik ini merinci tipe bilangan Erlang, mulai dari bilangan bulat presisi arbitrer, literal berbasis lain, aritmetika float, hingga operator logika dan aturan perbandingan antar tipe. Semua contoh dievaluasi nyata di shell OTP 29 sehingga setiap nilai, termasuk keluaran yang tampak aneh pada float, tertangkap apa adanya.

Bilangan bulat presisi arbitrer#

Bilangan bulat pada Erlang tidak memiliki batas ukuran yang menempel pada tipe mesin. Operasi boleh membesar tanpa risiko overflow karena VM mengelola memorinya sendiri. Perkalian berikut melampaui batas bilangan 64-bit, tetapi hasilnya tetap tepat:

erlang Perkalian bilangan besar
Erlang/OTP 29 [erts-17.1.1] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [jit:ns]

Eshell V17.1.1 (press Ctrl+G to abort, type help(). for help)
1> 123456789 * 987654321.
121932631112635269

Selain penulisan desimal, literal bilangan bulat mendukung basis lain dengan format Basis#Angka, serta literal karakter dengan awalan $. Ketiganya menghasilkan bilangan bulat biasa:

erlang Literal basis lain dan literal karakter
2> 2#1010.
10
3> 16#ff.
255
4> $A.
65

2#1010 adalah 10 dalam biner, 16#ff adalah 255 dalam heksadesimal, dan $A adalah kode karakter A sebesar 65. Bentuk-bentuk ini sering muncul saat bekerja dengan protokol biner dan penguraian teks pada topik penyimpanan dan binary.

Aritmetika float#

Bilangan float Erlang mengikuti standar double precision IEEE 754, sebagaimana umumnya bahasa modern. Operator pembagian / selalu menghasilkan float, sedangkan pembagian bilangan bulat dipakai lewat div dan sisa pembagiannya lewat rem:

erlang Pembagian dan sisa pembagian
5> 10 / 4.
2.5
6> 10 div 4.
2
7> 10 rem 4.
2
8> 10 / 2.
5.0

Perhatikan baris terakhir: 10 / 2. menghasilkan 5.0, bukan 5, karena operator / memang selalu float. Kebalikannya, div dan rem hanya menerima bilangan bulat dan menghasilkan bilangan bulat, sehingga campurannya perlu dikonversi secara eksplisit.

Presisi float membawa konsekuensi yang sebaiknya dikenal sejak awal. Sebagian bilangan desimal tidak dapat direpresentasikan persis dalam biner, sehingga hasil penjumlahannya tampak janggal:

erlang Keterbatasan presisi float
9> 0.1 + 0.2.
0.30000000000000004

Keluaran 0.30000000000000004 bukan bug Erlang, melainkan konsekuensi representasi biner IEEE 754 yang sama dengan bahasa lain. Untuk perhitungan yang menuntut ketepatan desimal penuh, misalnya nilai uang, menyimpan kelipatan integer atau penanganan khusus lebih aman daripada float mentah.

Konversi dan pemeriksaan tipe#

Karena / selalu float dan div murni bilangan bulat, konversi antara keduanya disediakan lewat fungsi khusus. Fungsi trunc/1 memotong bagian desimal, round/1 membulatkan ke bilangan terdekat, dan float/1 mengubah bilangan bulat menjadi float. Pemeriksaan tipe memakai keluarga fungsi is_integer/1, is_float/1, dan is_number/1 yang mengembalikan nilai kebenaran:

erlang Konversi dan pemeriksaan tipe bilangan
1> trunc(5.9).
5
2> round(5.4).
5
3> float(5).
5.0
4> is_integer(10).
true
5> is_number(2.5).
true

is_number/1 menerima keduanya, sedangkan is_integer/1 menolak float. Pembanding =:= membedakan tipe secara ketat, sehingga 2.0 =:= 2. bernilai false meski nilainya setara. Perbandingan == yang lebih longgar justru menghasilkan true. Perbedaan ini penting diingat saat membandingkan hasil pembagian dengan bilangan bulat, dan fungsi is_* kelak menjadi bahan utama guard pada modul ini.

Fungsi bawaan bilangan dan pembagian nol#

Selain operator, beberapa fungsi bawaan bilangan dipakai setiap hari. Fungsi abs/1 menghitung nilai mutlak, min/2 dan max/2 memilih bilangan terkecil atau terbesar, dan modul math menyediakan fungsi matematis seperti akar kuadrat dengan hasil float:

erlang Fungsi bawaan bilangan yang sering dipakai
1> math:sqrt(16).
4.0
2> abs(-7).
7
3> erlang:min(3, 9).
3
4> erlang:max(3, 9).
9

Pembagian dengan nol tidak menghasilkan nilai khusus, melainkan error. Baik 10 / 0. maupun 1 div 0. memicu exception aritmetika dengan pesan yang menyebut operator dan operandnya:

erlang Pembagian nol memicu error
5> 10 / 0.
** exception error: an error occurred when evaluating an arithmetic expression
     in operator  '/'/2
        called as 10 / 0
6> 1 div 0.
** exception error: an error occurred when evaluating an arithmetic expression
     in operator  div/2
        called as 1 div 0

Perilaku ini konsisten dengan filosofi bahasa: kejadian yang tidak seharusnya terjadi dilaporkan segera, bukan ditoleransi dengan nilai semu seperti tak hingga. Pemanggil yang tahu pembaginya bisa nol memeriksa nilainya terlebih dahulu, misalnya dengan cabang case atau guard yang dibahas pada modul ini.

true dan false serta operator logika#

Nilai kebenaran Erlang hanya dua, yaitu atom true dan atom false. Operator logika terbagi menjadi dua kelompok. Kelompok andalso dan orelse mengevaluasi sisi kedua hanya bila diperlukan, sedangkan and dan or selalu mengevaluasi kedua sisi:

erlang Evaluasi pendek pada andalso
10> 5 > 3 andalso 2 < 4.
true
11> false andalso (1 / 0 =:= 0).
false
12> false and (1 / 0 =:= 0).
** exception error: an error occurred when evaluating an arithmetic expression
     in operator  '/'/2
        called as 1 / 0

Ekspresi ke-11 menghasilkan false tanpa mengeksekusi 1 / 0, karena andalso berhenti begitu sisi pertama pasti false. Ekspresi ke-12 dengan operator and tetap mengevaluasi pembagian nol dan memicu error badarith. Perbedaan ini praktis: gunakan andalso dan orelse bila sisi kedua mahal atau berisiko error, dan and dengan or bila kedua sisi harus dihitung. Negasi memakai not, dan xor tersedia untuk gabungan eksklusif.

Urutan tipe pada perbandingan#

Operator < dan > dapat membandingkan nilai dari tipe berbeda karena seluruh tipe Erlang punya urutan total yang ditetapkan bahasa. Urutannya dari yang terkecil: bilangan, atom, reference, fun, port, PID, tuple, map, list, dan bitstring. Hasil nyatanya seperti berikut:

erlang Perbandingan lintas tipe
4> 1 < merah.
true
5> merah < {1}.
true
6> {1, 2} < [1].
true
7> [1] < <<"x">>.
true

Keempat perbandingan bernilai true dan masing-masing menaikkan satu tingkat tipe: bilangan di bawah atom, atom di bawah tuple, tuple di bawah list, dan list di bawah bitstring. Urutan total inilah yang membuat fungsi pengurutan seperti lists:sort/1 tetap bekerja pada list campuran, meski secara praktik membandingkan tipe yang tidak lazim dibandingkan biasanya merupakan tanda desain yang perlu ditinjau.

Ringkasan#

  • Bilangan bulat Erlang berpresisi arbitrer tanpa risiko overflow, dengan literal basis lain 2#1010 dan 16#ff serta literal karakter $A.
  • Operator / selalu menghasilkan float, sedangkan div dan rem murni bilangan bulat.
  • Float mengikuti IEEE 754 dan hasil semacam 0.1 + 0.2 = 0.30000000000000004 adalah konsekuensi representasinya.
  • andalso dan orelse mengevaluasi pendek, sedangkan and dan or selalu mengevaluasi kedua sisi.
  • trunc, round, dan float mengonversi antara bilangan bulat dan float, sedangkan keluarga is_integer, is_float, dan is_number memeriksa tipe.
  • Perbandingan lintas tipe mengikuti urutan total bahasa: bilangan, atom, reference, fun, port, PID, tuple, map, list, bitstring.

Referensi#