Topik ini membahas himpunan bilangan yang mendasari hampir semua perhitungan pada perangkat lunak, mulai dari bilangan asli, bilangan bulat, bilangan rasional, hingga bilangan real. Pembahasan kemudian menghubungkan hierarki tersebut dengan tipe float dan menjelaskan mengapa float bukan salinan setia dari bilangan real. Setelah topik ini dipahami, struktur bilangan beserta batas representasinya di komputer dapat diidentifikasi dengan tepat, termasuk alasan munculnya nilai seperti 0.30000000000000004.
Hierarki himpunan bilangan#
Bilangan pada matematika tersusun sebagai himpunan yang saling memuat. Bilangan asli adalah bilangan penghitungan yang digunakan untuk menyebut banyaknya objek. Bilangan bulat melengkapinya dengan nilai nol dan nilai negatif, sehingga berbentuk . Bilangan rasional mencakup semua bilangan yang dapat ditulis sebagai pecahan dengan dan bilangan bulat serta , misalnya dan . Hierarki keempat himpunan tersebut dirangkum dalam relasi berikut.
Bilangan real adalah himpunan terluar karena di dalamnya masih ada bilangan irasional, yaitu bilangan yang tidak dapat ditulis sebagai pecahan , contohnya dan . Pada garis bilangan, bilangan rasional dicirikan oleh desimal yang berhenti atau berulang secara teratur, sedangkan bilangan irasional memiliki perluasan desimal yang berlangsung tanpa pola berulang. Diagram berikut menampilkan susunan bertingkat tersebut beserta contoh anggotanya.
Setiap tingkat hierarki memiliki padanan yang lazim di kode. Bilangan asli dan bulat diwakili oleh tipe bilangan bulat seperti int, bilangan rasional dapat diwakili oleh tipe pecahan seperti Fraction, sedangkan bilangan real dihampiri oleh float. Padanan ini bekerja dengan baik selama batas masing-masing representasi dipahami, dan batas itulah yang dibahas pada bagian berikutnya.
Float sebagai hampiran bilangan real#
Float pada Python dan NumPy mengikuti standar IEEE 754 double precision yang menyimpan nilai dalam 64 bit yang terdiri atas satu bit tanda, sebelas bit eksponen, dan lima puluh dua bit fraksi. Dengan susunan tersebut, float hanya dapat menyimpan pecahan biner yang berhingga, sedangkan bilangan real mencakup bilangan yang perluasan binernya tak berhingga. Konsekuensinya, sebagian besar bilangan desimal hanya disimpan sebagai hampiran terdekat. Bilangan contohnya tidak memiliki bentuk biner berhingga karena perluasan binernya berulang tanpa akhir, sebagaimana ditunjukkan berikut.
Komputer menyimpan nilai yang paling dekat dengan dalam bentuk pecahan biner berhingga. Modul fractions pada Python dapat memperlihatkan pecahan yang benar-benar tersimpan di dalam float tersebut. Fungsi Fraction menerima float dan mengembalikan pecahan paling sederhana yang bernilai sama persis dengan float itu.
from fractions import Fraction
print(Fraction(0.1))
print(Fraction(0.5))3602879701896397/36028797018963968
1/2Keluaran di atas menunjukkan dua perilaku yang berbeda. Nilai tersimpan secara tepat karena adalah pecahan biner yang berhingga, sedangkan tersimpan sebagai pecahan yang hanya menghampiri . Selisihnya sangat kecil, tetapi selisih itu ikut terbawa ke setiap operasi berikutnya.
Batas representasi float#
Selain presisi yang terbatas, float juga memiliki batas rentang nilai dan batas ketepatan untuk bilangan bulat. Program berikut merangkum batas-batas itu secara langsung. Ketiganya dibaca dari atribut resmi modul sys, sehingga nilainya dapat diverifikasi ulang di lingkungan mana pun.
"""Batas representasi float IEEE 754 double precision."""
import sys
print("Nilai terbesar :", sys.float_info.max)
print("Epsilon mesin :", sys.float_info.epsilon)
print("0.1 + 0.2 =", repr(0.1 + 0.2))
print("0.1 + 0.2 == 0.3 ->", 0.1 + 0.2 == 0.3)
print("2**53 == 2**53 + 1 ->", 2.0**53 == 2.0**53 + 1)Nilai terbesar : 1.7976931348623157e+308
Epsilon mesin : 2.220446049250313e-16
0.1 + 0.2 = 0.30000000000000004
0.1 + 0.2 == 0.3 -> False
2**53 == 2**53 + 1 -> TrueTiga temuan pada keluaran tersebut penting untuk diingat. Pertama, nilai float terbesar adalah sekitar , dan perhitungan yang melewati nilai itu berubah menjadi inf. Kedua, epsilon mesin adalah jarak relatif terkecil yang masih dapat dibedakan di sekitar nilai 1.0, sehingga penambahan nilai yang lebih kecil daripada epsilon sering tidak berdampak apa pun. Ketiga, bilangan bulat hanya tersimpan tepat sampai , karena hanya itu jumlah bit yang tersedia untuk digit signifikan, sehingga mengalami pemotongan dan perbandingannya bernilai True padahal secara matematika salah.
Di mana hal ini ditemui dalam kode#
Masalah presisi ini bukan sekadar teori karena hampir setiap proyek perangkat lunak menyentuhnya. Pemrosesan uang lazim dihindarkan dari float dengan menyimpan nilai dalam satuan sen sebagai bilangan bulat, atau dengan tipe Decimal yang bekerja secara desimal. Penjumlahan jutaan nilai float pada perhitungan statistik atau machine learning menyebabkan selisih hampiran menumpuk menjadi kesalahan yang terlihat, sehingga algoritma numerik dirancang dengan memperhitungkan sifat ini. Fungsi math.fsum contohnya mengurangi penumpukan selisih ketika penjumlahan panjang tidak terhindarkan. Kasus yang paling sering ditemui adalah perbandingan kesamaan, dan NumPy menyediakan fungsi bantu untuk keperluan tersebut.
import numpy as np
a = 0.1 + 0.2
print(a == 0.3)
print(np.isclose(a, 0.3))
print(np.isclose(a, 0.3, atol=1e-17, rtol=0))False
True
FalseFungsi np.isclose menganggap dua nilai sama apabila selisihnya berada dalam toleransi, dengan toleransi relatif dan absolut yang dapat diatur. Pemanggilan ketiga pada contoh memperketat toleransi hingga , dan selisih hampiran terhadap yang besarnya sekitar kini dianggap tidak sama. Perilaku ini menegaskan bahwa toleransi adalah keputusan perancangan, bukan angka ajaib, dan nilai yang tepat bergantung pada besaran data yang diproses.
Ringkasan#
- Bilangan tersusun dalam hierarki , dan bilangan rasional berupa pecahan sedangkan bilangan real masih menambahkan bilangan irasional seperti .
- Float IEEE 754 hanya menyimpan pecahan biner berhingga dengan 53 bit digit signifikan, sehingga sebagian besar bilangan desimal hanya berupa hampiran, misalnya yang tersimpan sebagai .
- Batas praktis float adalah nilai terbesar sekitar , epsilon mesin , dan ketepatan bilangan bulat hanya sampai .
- Perbandingan kesamaan float sebaiknya dilakukan dengan toleransi seperti
np.isclose, atau perhitungan dialihkan ke representasi tepat sepertiintdanFractionketika presisi menentukan.
Referensi#
- Floating Point Arithmetic: Issues and Limitations — Python Software Foundation
— Penjelasan resmi mengapa aritmetika float menghasilkan nilai seperti
0.30000000000000004. - NumPy 2.1 documentation — NumPy Developers
— Dokumentasi
numpy.isclosebeserta aturan toleransi relatif dan absolut yang digunakan pada bagian akhir topik. - Prealgebra 2e — OpenStax — Buku teks terbuka yang membahas himpunan bilangan beserta operasinya pada bab-bab awal.