Standar IEEE 754-2008 untuk Floating-Point Arithmetic dan ISO / IEC 10967 Language Independent Arithmetic (LIA) Standard, Bagian 1 menjawab mengapa demikian.
IEEE 754 § 6.3 Tanda itu sedikit
Ketika input atau hasil adalah NaN, standar ini tidak menafsirkan tanda NaN. Perhatikan, bagaimanapun, bahwa operasi pada string bit - copy, negate, abs, copySign - tentukan bit tanda dari hasil NaN, kadang-kadang berdasarkan bit tanda operan NaN. TotalOrder predikat logis juga dipengaruhi oleh bit tanda operan NaN. Untuk semua operasi lain, standar ini tidak menentukan bit tanda hasil NaN, bahkan ketika hanya ada satu input NaN, atau ketika NaN dihasilkan dari operasi yang tidak valid.
Ketika input atau hasil bukan NaN, tanda suatu produk atau hasil bagi adalah OR eksklusif atau dari tanda operan; tanda penjumlahan, atau perbedaan x - y dianggap sebagai penjumlahan x + (−y), berbeda dari paling banyak salah satu dari tanda-tanda tambahan; dan tanda hasil konversi, operasi kuantisasi, operasi roundTo-Integral, dan roundToIntegralExact (lihat 5.3.1) adalah tanda operan pertama atau satu-satunya. Aturan-aturan ini akan berlaku bahkan ketika operan atau hasilnya nol atau tidak terbatas.
Ketika jumlah dua operan dengan tanda-tanda yang berlawanan (atau perbedaan dari dua operan dengan tanda-tanda serupa) adalah nol, tanda dari jumlah (atau perbedaan) tersebut harus +0 dalam semua atribut arah pembulatan kecuali roundTowardNegative; di bawah atribut itu, tanda jumlah nol yang tepat (atau perbedaan) harus −0. Namun, x + x = x - (−x) mempertahankan tanda yang sama dengan x bahkan ketika x adalah nol.
Kasus Penambahan
Di bawah mode pembulatan standar (Round-to-Nearest, Ties-to-Even) , kita melihat bahwa x+0.0menghasilkan x, KECUALI ketika xadalah -0.0: Dalam hal itu kita memiliki jumlah dua operan dengan tanda-tanda berlawanan yang jumlahnya adalah nol, dan §6,3 paragraf 3 aturan yang dihasilkan tambahan ini +0.0.
Karena bitwise+0.0 tidak identik dengan aslinya , dan itu adalah nilai yang sah yang dapat terjadi sebagai input, kompiler wajib memasukkan kode yang akan mengubah nol potensial menjadi negatif .-0.0-0.0+0.0
Ringkasan: Di bawah mode pembulatan default, dalam x+0.0, jikax
- tidak
-0.0 , maka xitu sendiri adalah nilai output yang dapat diterima.
- adalah
-0.0 , maka nilai output harus +0.0 , yang tidak identik dengan bitwise -0.0.
Kasus Multiplikasi
Di bawah mode pembulatan default , tidak ada masalah seperti itu terjadi x*1.0. Jika x:
Kasus Pengurangan
Di bawah mode pembulatan default , pengurangan x-0.0juga merupakan larangan, karena setara dengan x + (-0.0). Jika xada
- adalah
NaN, maka §6.3p1 dan §6.2.3 berlaku dengan cara yang sama seperti untuk penambahan dan penggandaan.
- adalah
+/- infinity, maka hasilnya adalah +/- infinitydari tanda yang sama.
- adalah (normal) angka normal,
x-0.0 == xselalu.
- adalah
-0.0, maka oleh §6.3p2 kita memiliki " [...] tanda penjumlahan, atau perbedaan x - y dianggap sebagai penjumlahan x + (fromy), berbeda dari paling banyak salah satu dari tanda tambahan; ". Ini memaksa kita untuk menetapkan -0.0sebagai hasil dari (-0.0) + (-0.0), karena -0.0berbeda dalam tanda dari tidak ada tambahan, sementara +0.0berbeda dalam tanda dari dua dari tambahan, yang melanggar pasal ini.
- adalah
+0.0, maka ini mengurangi kasus penambahan yang (+0.0) + (-0.0)dipertimbangkan di atas dalam Kasus Penambahan , yang oleh §6.3p3 diperintahkan untuk diberikan +0.0.
Karena untuk semua kasus, nilai input legal sebagai output, diizinkan untuk mempertimbangkan x-0.0larangan, dan x == x-0.0tautologi.
Optimalisasi Perubahan Nilai
Standar IEEE 754-2008 memiliki kutipan menarik berikut:
IEEE 754 § 10.4 Arti literal dan optimisasi yang mengubah nilai
[...]
Transformasi yang mengubah nilai berikut, antara lain, mempertahankan makna literal kode sumber:
- Menerapkan properti identitas 0 + x ketika x bukan nol dan bukan NaN pensinyalan dan hasilnya memiliki eksponen yang sama dengan x.
- Menerapkan properti identitas 1 × x ketika x bukan NaN pensinyalan dan hasilnya memiliki eksponen yang sama dengan x.
- Mengubah muatan atau masuk sedikit NaN yang tenang.
- [...]
Karena semua NaN dan semua infinities berbagi eksponen yang sama, dan hasil benar bulat x+0.0dan x*1.0untuk yang terbatas xmemiliki tepat besarnya sama x, eksponen mereka adalah sama.
sNaNs
Signalling NaNs adalah nilai perangkap floating-point; Mereka adalah nilai NaN khusus yang digunakan sebagai operan titik-mengambang menghasilkan pengecualian operasi tidak valid (SIGFPE). Jika loop yang memicu pengecualian dioptimalkan, perangkat lunak tidak akan lagi berperilaku sama.
Namun, seperti yang ditunjukkan oleh user2357112 dalam komentar , Standar C11 secara eksplisit membiarkan perilaku pensinyalan NaNs ( sNaN), sehingga penyusun diizinkan untuk menganggap mereka tidak terjadi, dan dengan demikian pengecualian yang mereka ajukan juga tidak terjadi. C ++ 11 menghilangkan standar yang menggambarkan perilaku untuk memberi sinyal NaN, dan dengan demikian juga membiarkannya tidak terdefinisi.
Mode Pembulatan
Dalam mode pembulatan alternatif, optimisasi yang diizinkan dapat berubah. Misalnya, dalam mode Round-to-Negative-Infinity , optimasi x+0.0 -> xmenjadi diizinkan, tetapi x-0.0 -> xmenjadi terlarang.
Untuk mencegah GCC dari mengasumsikan mode dan perilaku pembulatan default, bendera eksperimental -frounding-mathdapat diteruskan ke GCC.
Kesimpulan
Dentang dan GCC , bahkan pada -O3, tetap sesuai IEEE-754. Ini berarti harus mematuhi aturan standar IEEE-754 di atas. x+0.0adalah tidak bit-identik untuk xsemua xdi bawah aturan-aturan, tetapi x*1.0 dapat dipilih untuk menjadi begitu : Yaitu, ketika kita
- Patuhi rekomendasi untuk meneruskan payload yang tidak berubah
xketika itu adalah NaN.
- Biarkan sedikit tanda hasil NaN tidak diubah oleh
* 1.0.
- Mematuhi perintah untuk XOR tanda sedikit selama quotient / produk, saat
xini tidak NaN.
Untuk mengaktifkan pengoptimalan yang tidak aman dari IEEE-754 (x+0.0) -> x, flag tersebut -ffast-mathharus diteruskan ke Dentang atau GCC.