Saya sedang membaca artikel dari Microsoft tentang Pelebaran Konversi dan Opsi Ketat Aktif ketika saya sampai di bagian tersebut
Konversi berikut mungkin kehilangan presisi:
- Integer ke Tunggal
- Panjang ke Tunggal atau Ganda
- Desimal ke Satu atau Ganda
Namun, konversi ini tidak kehilangan informasi atau besarnya.
.. tetapi menurut artikel lain mengenai tipe data ,
Tipe integer dapat menyimpan dari -2.147.483.648 hingga 2.147.483.647 dan
Jenis tunggal dapat menyimpan dari
- 1,401298E-45 hingga 3,4028235E + 38 untuk angka positif,
- dan -3,4028235E + 38 hingga - 1,401298E-45 untuk angka negatif
.. jadi Single dapat menyimpan lebih banyak angka daripada Integer. Saya tidak dapat memahami dalam situasi apa konversi seperti itu dari Integer ke Single dapat kehilangan presisi. Bisakah seseorang menjelaskannya?
sumber
Integer
s (99,2%) tidak dapat direpresentasikan sebagaiSingle
, jadi "ketika" adalah "hampir selalu".Single
hanya dapat mewakili 4.278.190.079 angka berbeda. SebuahSingle
nilai mewakili nomor jika dan hanya jika eksponen disimpan tidak 255, yang berarti bahwa ada 255 * 2 ^ 24Single
s yang mewakili angka. Dari ini, dua dari mereka mewakili angka yang sama (yaitu, nol), dan yang lainnya semuanya mewakili angka yang berbeda.[-16777216,16777216]
(2 ^ 24 = lebar signifikan dan) dapat direpresentasikan dengan tepat. Angka yang lebih besar dibulatkan ke kelipatan terdekat 2, 4, 8, ... tergantung pada seberapa besar mereka.Single
memiliki dua cara menyimpan nol. JadiSingle
sebenarnya bisa mewakili angka yang berbeda lebih sedikit daripadaInteger
.Tipe floating point (seperti Single dan Double) diwakili dalam memori oleh tanda, mantissa dan eksponen. Anggap saja sebagai notasi ilmiah:
Mereka - seperti yang Anda duga - menggunakan basis 2. Ada tweak lain yang memungkinkan untuk merepresentasikan infinity dan NaN, dan eksponen diimbangi (akan kembali ke sana), dan sebuah singkatan untuk mantissa (akan kembali ke sana juga) . Cari IEEE 754 standar yang mencakup perwakilan dan operasinya untuk detail lebih lanjut.
Untuk keperluan kita, kita dapat membayangkannya sebagai angka biner "mantissa", dan "eksponen" yang memberi tahu Anda di mana harus meletakkan pemisah desimal.
Dalam kasus Single, kita memiliki 1 bit untuk dia tanda tangani, 8 untuk eksponen dan 23 untuk mantissa.
Sekarang, masalahnya, kita akan menyimpan mantissa dari angka paling signifikan. Ingatlah bahwa semua nol di sebelah kiri tidak relevan. Dan memberi bahwa kita bekerja dalam biner, kita tahu bahwa digit paling signifikan adalah 1 ※. Yah, karena kita tahu itu, kita tidak harus menyimpannya. Berkat steno itu, jangkauan efektif mantra adalah 24 bit.
※: Kecuali jika nomor yang kita simpan adalah nol. Untuk itu kita akan mengatur semua bit ke nol. Namun, jika kita mencoba menafsirkan bahwa di bawah deskripsi yang saya berikan, Anda akan memiliki 2 ^ 24 (yang implisit 1) dikalikan dengan 1 (2 pangkat eksponen 0). Jadi, untuk memperbaikinya, nol eksponen adalah nilai khusus. Ada juga nilai-nilai khusus untuk menyimpan infinity dan NaN dalam eksponen.
Sesuai offset eksponen - selain menghindari nilai-nilai khusus - memiliki offset itu memungkinkan untuk menempatkan titik desimal sebelum dimulainya mantissa atau setelah akhirnya, tanpa perlu memiliki tanda untuk eksponen.
Ini berarti bahwa untuk jumlah besar, tipe floating point akan menempatkan titik desimal di luar akhir mantissa.
Ingat bahwa mantissa adalah angka 24 bit. Itu tidak akan pernah mewakili nomor 25 bit ... tidak memiliki bit ekstra itu. Dengan demikian, tunggal tidak dapat membedakan antara 2 ^ 24 dan 2 ^ 24 + 1 (ini adalah angka bit 25 pertama, dan mereka berbeda pada bit terakhir, yang tidak terwakili dalam single).
Jadi, untuk bilangan bulat kisaran tunggal adalah -2 ^ 24 hingga 2 ^ 24. Dan mencoba menambahkan 1 ke 2 ^ 24 akan menghasilkan 2 ^ 24 (karena sejauh menyangkut jenisnya, 2 ^ 24 dan 2 ^ 24 + 1 adalah nilai yang sama). Cobalah secara Online . Inilah sebabnya mengapa ada kehilangan informasi ketika mengkonversi dari integer ke single. Dan ini juga mengapa loop yang menggunakan satu atau ganda sebenarnya bisa menjadi loop tanpa batas tanpa Anda sadari.
sumber
1
bit terkemuka implisit dalam signifikansi. Ini tersirat oleh bidang bias-eksponen menjadi nol . Subnormal (alias denormals) termasuk+-0.0
memiliki0
sedikit terkemuka signifikansinya. Saya kira Anda dapat menyederhanakan untuk hanya mempertimbangkan0.0
kasus yang benar-benar istimewa, tetapi0.0
sebenarnya mengikuti aturan penyandian yang sama seperti subnormal lainnya.Berikut ini adalah contoh aktual saat mengkonversi dari
Integer
menjadiSingle
mungkin kehilangan presisi:The
Single
jenis dapat menyimpan semua bilangan bulat dari -16777216 ke 16777216 (inklusif), tetapi tidak dapat menyimpan semua bilangan bulat di luar kisaran ini. Sebagai contoh, tidak dapat menyimpan jumlah 16777217. Untuk itu, tidak dapat menyimpan setiap nomor lebih besar yang aneh dari 16.777.216.Kita dapat menggunakan Windows PowerShell untuk melihat apa yang terjadi jika kita mengonversikan
Integer
keSingle
dan kembali:Perhatikan bahwa 16777217 dibulatkan ke 16777216, dan 16777219 dibulatkan ke 16777220.
sumber
float
terus tumbuh sebagai kekuatan. en.wikipedia.org/wiki/…Jenis titik apung mirip dengan "notasi ilmiah" dalam fisika. Angka tersebut dibagi menjadi bit tanda, eksponen (pengali) dan mantissa (angka signifikan). Jadi karena besarnya nilai meningkat ukuran langkah juga meningkat.
Floating point presisi tunggal memiliki 23 bit mantissa, tetapi ada "implisit 1", sehingga mantissa efektif 24 bit. Oleh karena itu semua bilangan bulat dengan magnitudo hingga 24 dapat diwakili secara tepat dalam floating point presisi tunggal.
Di atas angka yang lebih sedikit berturut-turut dapat diwakili.
Jadi dari 2 32 kemungkinan nilai integer bertanda 32 bit hanya 2 * (2 24 + 7 * 2 23 ) = 9 * 2 24 dapat direpresentasikan dalam floating point presisi tunggal. Itu adalah 3,515625% dari total.
sumber
Pelampung presisi tunggal memiliki 24 bit presisi. Apa pun yang dibulatkan ke angka 24-bit terdekat. Mungkin lebih mudah dipahami dalam notasi ilmiah desimal, tetapi perlu diingat float aktual menggunakan biner.
Katakanlah Anda memiliki 5 digit desimal memori. Anda dapat memilih untuk menggunakan yang seperti int unsigned biasa, memungkinkan Anda untuk memiliki angka antara 0 dan 99999. Jika Anda ingin dapat mewakili angka yang lebih besar, Anda dapat menggunakan notasi ilmiah dan hanya mengalokasikan dua digit sebagai eksponen, jadi Anda sekarang dapat mewakili apa pun antara 0 dan 9,99 x 10 99 .
Namun, angka terbesar yang Anda dapat wakili dengan tepat sekarang hanya 999. Jika Anda mencoba mewakili 12345, Anda bisa mendapatkan 1,23 x 10 4 , atau 1,24 x 10 4 , tetapi Anda tidak dapat mewakili angka apa pun di antaranya, karena Anda tidak memiliki cukup angka.
sumber