Belajar dengan membaca secara berurutan

decimal dan fractions — Aritmetika Presisi tanpa Error Float

Pelajari modul decimal dan fractions Python dari dasar. Mencakup masalah 0.1 + 0.2 != 0.3 dengan float, perhitungan uang yang tepat dengan Decimal (dan kenapa kamu membuat Decimal dari string), aritmetika dengan Fraction yang otomatis disederhanakan, dan memilih di antara tiga tipe numerik — dengan latihan praktik yang bisa dijalankan.

Artikel ini membahas dua modul untuk kasus di mana `float` menyebabkan masalah. decimal.Decimal melakukan aritmetika base-10 yang tepat, yang menjadikannya esensial untuk perhitungan uang; fractions.Fraction menjaga pembilang dan penyebut sebagai integer sehingga bisa menghitung dengan pecahan tersederhanakan secara tepat. Keduanya ada untuk menghilangkan error pembulatan yang tak terhindarkan dari float.

Error Pembulatan Float dan decimal.Decimal — Jangan Pakai Float untuk Matematika Presisi

float Python direpresentasikan secara internal dalam biner, jadi pecahan desimal seperti `0.1` yang tidak terbagi rapi dalam biner membawa error pembulatan kecil. Contoh paling terkenal adalah `0.1 + 0.2 == 0.3` yang mengembalikan `False`. Untuk grafik atau komputasi ilmiah error itu bisa diabaikan, tapi dalam penjumlahan finansial bahkan sedikit drift menjadi kritis.

Itulah sebabnya decimal.Decimal ada. Ia direpresentasikan secara internal dalam base 10, jadi membuat satu dari string "0.1" memungkinkanmu menghitung tanpa error.

float vs Decimal
float0.1 + 0.2→ 0.30000000000000004error pembulatanDecimalDecimal('0.1') + Decimal('0.2')→ Decimal('0.3')tanpa error
float cepat (instruksi CPU) tapi memperkenalkan error pembulatan dengan nilai seperti 0.1. Decimal menggunakan representasi internal base-10, jadi menghitung tepat seperti string masukan mengatakannya, tapi lebih lambat dari float. Untuk pemrosesan uang dan pajak, pilih Decimal.
from decimal import Decimal

# error pembulatan float
print(0.1 + 0.2)              # 0.30000000000000004
print(0.1 + 0.2 == 0.3)       # False  ← berlawanan dengan intuisi!

# Buat Decimal dari string (dari float akan mewarisi error)
a = Decimal("0.1")
b = Decimal("0.2")
print(a + b)                  # 0.3
print(a + b == Decimal("0.3"))  # True

# Contoh perhitungan uang
price = Decimal("1980")
tax_rate = Decimal("0.10")
total = price * (Decimal("1") + tax_rate)
print(total)                  # 2178.00

Buat Decimal dari string, bukan dari float

Kalau kamu memberi float — Decimal(0.1) — kamu menyerahkan nilai yang sudah membawa error pembulatan, jadi kamu berakhir dengan Decimal yang masih punya error float-nya. Selalu beri string: Decimal("0.1"). Sulit terlihat di test dan ini jebakan klasik yang menghasilkan drift satu sen di production untuk pertama kalinya.

Pertama amati error pembulatan float, lalu beralih ke Decimal untuk perhitungan termasuk pajak yang tepat.

① Import Decimal dari modul decimal.

② Hitung 0.1 + 0.2 dengan float dan cetak sebagai float: ◯◯ (kamu harus melihat error-nya).

③ Cetak hasil dari 0.1 + 0.2 == 0.3 sebagai float equal?: ◯◯ (mengembalikan False, berlawanan intuisi).

④ Hitung 0.1 + 0.2 dengan Decimal dan cetak sebagai Decimal: ◯◯ (tanpa error kali ini).

⑤ Definisikan harga sebelum pajak 1980 dan tarif pajak 10% sebagai Decimal, hitung total termasuk pajak, dan cetak sebagai total: ◯◯.

Python Editor

Jalankan kode untuk melihat output

fractions.Fraction — Menjaga Pecahan tetap Pecahan

Fraction adalah tipe yang menyimpan pembilang dan penyebut sebagai integer untuk aritmetika. Buat satu dengan Fraction(1, 3), dan penjumlahan, pengurangan, dan perkalian berikutnya mengembalikan hasil pecahan tersederhanakan. Sebagai float, 1/3 adalah aproksimasi 0.3333333333333333, tapi dengan Fraction ia tetap sebagai "sepertiga" itu sendiri.

Sekilas Fraction
Fraction(1, 3)+ Fraction(1, 6)Fraction(1, 2)(otomatis disederhanakan)
Buat dengan Fraction(pembilang, penyebut) — tipe rasio integer. Hasil dari + / - / * juga Fraction, dan otomatis disederhanakan. Kamu bisa konversi ke float dengan float(f), tapi itu memperkenalkan error pembulatan.
TipeRepresentasi internalPaling cocok untuk
intIntegerHitungan dan pencatatan (tanpa error)
floatFloating-point binerKomputasi ilmiah, grafik (cepat, dengan error)
DecimalRepresentasi base-10Uang dan pajak (saat presisi base-10 penting)
FractionPembilang dan penyebut (integer)Rasio dan probabilitas (saat ingin bentuk tersederhanakan)

Objek Fraction mengekspos atribut untuk pembilang dan penyebut. f.numerator mengembalikan pembilang dan f.denominator mengembalikan penyebut — keduanya setelah penyederhanaan. Misalnya, Fraction(2, 6) dinormalisasi secara internal menjadi Fraction(1, 3), jadi .numerator adalah 1 dan .denominator adalah 3.

Atribut / MethodArtiContoh
f.numeratorPembilangFraction(1, 3).numerator → 1
f.denominatorPenyebutFraction(1, 3).denominator → 3
float(f)Konversi ke floatfloat(Fraction(1, 2)) → 0.5

Tambahkan dua pecahan dan akses atribut dari hasilnya. Hitung 1/3 + 1/6 sambil menjaganya sebagai Fraction, dan konfirmasi bahwa jawabannya otomatis disederhanakan.

① Import Fraction dari modul fractions.

② Buat 1/3 dan 1/6 sebagai Fraction.

③ Tambahkan keduanya dan cetak hasilnya sebagai sum: ◯/◯ (harus otomatis disederhanakan).

④ Baca pembilang dan penyebut dari hasilnya via atribut, dan cetak sebagai numerator: ◯ denominator: ◯.

⑤ Konversi hasilnya ke float dan cetak sebagai as float: ◯.◯.

Python Editor

Jalankan kode untuk melihat output
QUIZ

Cek Pemahaman

Jawab setiap pertanyaan satu per satu.

Soal 1Pilihan yang paling tepat ketika kamu tidak bisa mentolerir bahkan satu sen drift dalam perhitungan uang?

Soal 2Saat membuat Decimal, cara benar yang tidak memperkenalkan error?

Soal 3Kamu pakai yang mana saat ingin menghitung rasio atau probabilitas sebagai pecahan tersederhanakan?