Yang merupakan bilangan bulat pertama yang pelampung IEEE 754 tidak mampu mewakili tepatnya?

162

Untuk kejelasan, jika saya menggunakan bahasa yang mengimplementasikan IEE 754 floats dan saya menyatakan:

float f0 = 0.f;
float f1 = 1.f;

... dan kemudian mencetaknya kembali, saya akan mendapatkan 0,0000 dan 1,0000 - tepatnya.

Tetapi IEEE 754 tidak mampu mewakili semua angka di sepanjang garis nyata. Mendekati nol, celahnya kecil; saat Anda semakin jauh, jarak semakin besar.

Jadi, pertanyaan saya adalah: untuk pelampung IEEE 754, yang merupakan bilangan bulat pertama (paling dekat dengan nol) yang tidak dapat direpresentasikan secara tepat? Saya hanya benar-benar peduli dengan mengapung 32-bit untuk saat ini, meskipun saya akan tertarik untuk mendengar jawabannya untuk 64-bit jika seseorang memberikannya!

Saya pikir ini akan sesederhana menghitung 2 bits_of_mantissa dan menambahkan 1, di mana bits_of_mantissa adalah berapa banyak bit yang diekspos standar. Saya melakukan ini untuk mengapung 32-bit pada mesin saya (MSVC ++, Win64), dan sepertinya baik-baik saja.

Floomi
sumber
Mengapa Anda menambahkan satu jika Anda menginginkan nomor yang tidak dapat ditampilkan? Dan nomor apa yang Anda gunakan atau dapatkan? Dan apakah ini pekerjaan rumah? Dan judul pertanyaan Anda mengatakan "integer" tetapi pertanyaan Anda mengatakan "float".
msw
5
Karena saya pikir maxing mantissa akan memberi saya angka representable tertinggi. 2 ^ 22. Tidak, ini pertanyaan penasaran. Saya selalu merasa bersalah meletakkan int di pelampung, bahkan ketika saya tahu bahwa int yang dipermasalahkan akan selalu sangat kecil. Saya ingin tahu apa batas atasnya. Sejauh yang saya tahu, judul dan pertanyaannya sama, hanya diutarakan secara berbeda.
Floomi
1
@KyleStrand dikembalikan ^ 2. Saya tidak tahu mengapa yang satu tampak lebih benar bagi saya daripada yang lain pada saat itu. Sekarang mereka berdua tampak canggung dibandingkan dengan "... adalah jumlah bit ..."
Pascal Cuoq

Jawaban:

211

2 mantissa bit + 1 + 1

+1 dalam eksponen (mantissa bits + 1) adalah karena, jika mantissa berisi abcdef...angka yang diwakilinya sebenarnya 1.abcdef... × 2^e, memberikan bit presisi ekstra implisit.

Oleh karena itu, bilangan bulat pertama yang tidak dapat diwakili secara akurat dan akan dibulatkan adalah:
Untuk float, 16.777.217 (2 24 + 1).
Untuk double, 9.007.199.254.740.993 (2 53 + 1).

>>> 9007199254740993.0
9007199254740992
kennytm
sumber
Saya mendeklarasikan floatdan mengaturnya sama dengan 16.777.217. Tetapi ketika saya mencetaknya menggunakannya coutmenghasilkan 16.777.216. Saya menggunakan C++. Mengapa saya tidak bisa mendapatkan 16.777.217?
sodiumnitrate
18
@sodiumnitrate Periksa judul pertanyaan. 16777217 adalah bilangan bulat pertama yang tidak dapat diwakili secara tepat.
kennytm
Ok terima kasih. Saya bingung, maaf soal itu. Saya punya pertanyaan lain: setelah 16777216, bukankah seharusnya bilangan bulat berikutnya yang diwakili menjadi 2 * 16777216? Ketika saya menjalankan program serupa, saya mendapatkan 16777218 dengan menambahkan 2 hingga 16777126.
sodiumnitrate
5
Bilangan bulat berikutnya memang 16777218, karena 2 sekarang menjadi digit biner signifikan terakhir.
kennytm
6
Di C ++, itu (1 << std::numeric_limits<float>::digits) + 1, dan di C (1 << FLT_MANT_DIG) + 1,. Yang pertama itu bagus karena bisa menjadi bagian dari templat. Jangan tambahkan +1 jika Anda hanya ingin integer representable terbesar.
Henry Schreiner
38

Nilai terbesar yang dapat diwakili oleh integer n bit adalah 2 n -1. Seperti disebutkan di atas, a floatmemiliki 24 bit presisi dalam arti yang tampaknya menyiratkan bahwa 24 tidak cocok.

Namun demikian .

Pangkat 2 dalam kisaran eksponen persis direpresentasikan sebagai 1,0 × 2 n , sehingga 2 24 dapat cocok dan akibatnya bilangan bulat tak terwakili pertama floatadalah 2 24 +1. Seperti disebutkan di atas. Lagi.

demikian bicaranya ak
sumber
1
Ini dengan jelas menjelaskan bagian "presisi ekstra implisit" dari yang lain. Terima kasih.
chappjc