Bagaimana Lua menangani angka integer dan float?

11

Sejauh yang saya ingat pada diri saya sendiri pemrograman saya diajarkan untuk tidak membandingkan angka floating point untuk kesetaraan. Sekarang, ketika membaca Pemrograman di Lua tentang numbertipe Lua , saya menemukan berikut:

Jenis angka mewakili angka nyata (titik presisi mengambang-ganda). Lua tidak memiliki tipe integer, karena tidak memerlukannya. Ada kesalahpahaman yang tersebar luas tentang kesalahan aritmatika floating-point dan beberapa orang takut bahwa kenaikan sederhana pun bisa aneh dengan angka floating-point. Faktanya adalah bahwa, ketika Anda menggunakan ganda untuk mewakili integer, tidak ada kesalahan pembulatan sama sekali (kecuali jumlahnya lebih dari 100.000.000.000.000). Secara khusus, nomor Lua dapat mewakili bilangan bulat panjang tanpa masalah pembulatan. Selain itu, sebagian besar CPU modern melakukan aritmatika floating-point secepat (atau bahkan lebih cepat dari) aritmatika integer.

Apakah itu berlaku untuk semua bahasa? Pada dasarnya jika kita tidak melampaui floating point dalam dobel, kita aman dalam aritmatika bilangan bulat? Atau, agar lebih sesuai dengan judul pertanyaan, apakah ada sesuatu yang istimewa yang Lua lakukan dengan numbertipenya sehingga berfungsi dengan baik sebagai tipe integer dan float-point?

Petr Abdulin
sumber
Lihat juga stackoverflow.com/questions/1848700/…
Joonas Pulakka
@JoonasPulakka terima kasih, itu tambahan yang cukup berharga.
Petr Abdulin

Jawaban:

11

Lua mengklaim bahwa angka floating point dapat mewakili angka integer sama persis dengan tipe integer, dan saya cenderung setuju. Tidak ada representasi bagian numerik fraksional yang tidak tepat untuk ditangani. Apakah Anda menyimpan bilangan bulat dalam tipe bilangan bulat, atau menyimpannya di mantissa dari angka floating point, hasilnya sama: bilangan bulat itu dapat direpresentasikan dengan tepat, selama Anda tidak melebihi jumlah bit dalam mantissa , + 1 bit dalam eksponen.

Tentu saja, jika Anda mencoba untuk menyimpan angka floating-point aktual (mis. 12.345) dalam representasi floating point, semua taruhan dimatikan, sehingga program Anda harus jelas bahwa angka tersebut benar-benar bilangan bulat asli yang tidak membanjiri mantissa, untuk memperlakukannya seperti bilangan bulat yang sebenarnya (yaitu sehubungan dengan membandingkan kesetaraan).

Jika Anda membutuhkan presisi integer lebih dari itu, Anda selalu dapat menggunakan pustaka presisi arbitrer .

Bacaan Lebih Lanjut
Berapa nilai maksimum suatu angka dalam Lua?

Robert Harvey
sumber
Bagaimana dengan argumen kedua mereka, yaitu bahwa floating point lebih cepat atau lebih cepat daripada integer aritmatika di CPU modern? Kedengarannya meragukan bagi saya, bahkan ketika menggunakan angka floating point untuk melakukan bilangan aritmatika.
Andres F.
2
@AndresF. Saya tidak melihat bagaimana ini lebih cepat, kecuali Anda menghilangkan gips dengan menggunakan tipe numerik tunggal alih-alih dua.
Robert Harvey
Sepakat. Tidak masuk akal bagi saya. Saya ingin tahu apakah itu diambil di luar konteks ...
Andres F.
1
Bilangan bulat yang cukup besar tidak dapat disimpan dengan tepat di objek titik-mengambang. 64-bit doublememiliki sekitar 51 atau lebih mantissa bit; bilangan bulat ganjil yang lebih besar dari sekitar 2 ** 51 akan memiliki kesalahan pembulatan. Bilangan bulat 64-bit dapat menyimpan nilai bilangan bulat yang lebih besar dengan tepat, karena tidak mencurahkan bit apa pun untuk eksponen.
Keith Thompson
@KeithThompson: Saya pikir itu tersirat dalam jawaban saya ketika saya mengatakan "disimpan di mantissa." Namun, saya akan mengedit jawaban untuk menjelaskan.
Robert Harvey
6

Ganda disimpan sebagai mantissa dan eksponen. Lihat format untuk informasi lebih lanjut. Pada dasarnya, semua angka adalah dalam bentuk: mantissa * 2 eksponen . Untuk bilangan bulat mana pun yang lebih kecil dari 2 52 , eksponen akan menjadi nol, membuat mantissa bit-for-bit setara dengan bilangan bulat unsigned 52-bit. Bit tanda terpisah digunakan untuk menunjukkan angka negatif.

Bahkan, bahkan beberapa bilangan bulat yang lebih besar dari 2 52 dapat direpresentasikan dengan tepat, selama semua digit yang melewati 52 nd adalah nol. Juga, beberapa fraksi, seperti 0,5, dapat direpresentasikan secara tepat. Hanya ketika fraksi terus berulang (seperti 1/3) di basis 2, atau membutuhkan terlalu banyak bit melewati titik radix yang Anda kehilangan presisi.

Karl Bielefeldt
sumber
Itu bukan karena desimal yang terus berulang. Itu karena banyak angka desimal (basis sepuluh) tidak dapat direpresentasikan persis sebagai kekuatan dua.
Robert Harvey
3
Di basis 2, angka yang tidak dapat direpresentasikan dengan tepat akan terus berulang. Sebagai contoh, 0,1 desimal menjadi 0,0 (0011) dalam biner, dengan 0011 terus berulang.
Karl Bielefeldt
3
Ya persis. Tetapi tidak mengulangi di basis 10. Mengulangi di basis 2.
Robert Harvey