Kayan Nokta Aritmetiği için IEEE 754-2008 Standardı ve ISO / IEC 10967 Dilden Bağımsız Aritmetik (LIA) Standardı, Bölüm 1 bunun neden böyle olduğunu yanıtlıyor.
IEEE 754 § 6.3 İşaret biti
Bir girdi veya sonuç NaN olduğunda, bu standart bir NaN'nin işaretini yorumlamaz. Bununla birlikte, bit dizelerindeki işlemlerin - copy, negate, abs, copySign - bazen bir NaN işleneninin işaret bitine bağlı olarak bir NaN sonucunun işaret bitini belirttiğini unutmayın. TotalOrder mantıksal yüklemi ayrıca bir NaN işleneninin işaret bitinden de etkilenir. Diğer tüm işlemler için, bu standart, yalnızca bir NaN girişi olduğunda veya geçersiz bir işlemden NaN üretildiğinde bile bir NaN sonucunun işaret bitini belirtmez.
Ne girdiler ne de sonuç NaN olmadığında, bir çarpımın veya bölümün işareti işlenenlerin işaretlerinin dışlayıcı VEYA'sıdır; x + (xy) toplamı olarak kabul edilen bir toplamın veya bir x - y farkının işareti, en fazla toplananların işaretlerinden birinden farklıdır; ve dönüşümlerin sonucunun işareti, niceleme işlemi, roundTo-Integral işlemleri ve roundToIntegralExact (bkz. 5.3.1), ilk veya tek işlenenin işaretidir. Bu kurallar, işlenenler veya sonuçlar sıfır veya sonsuz olduğunda bile geçerli olacaktır.
Karşıt işaretli iki işlenen toplamı (veya benzer işaretli iki işlenen arasındaki fark) tam olarak sıfır olduğunda, bu toplamın (veya farkın) işareti roundTowardNegative hariç tüm yuvarlama yönü özelliklerinde +0 olacaktır; bu nitelik altında, tam bir sıfır toplamın (veya farkın) işareti −0 olacaktır. Bununla birlikte, x + x = x - (−x), x sıfır olduğunda bile x ile aynı işareti korur.
Ekleme Durumu
Varsayılan yuvarlama modu altında (Gidiş-to-yakın, Kravatlar-to-bile) bunu görmek x+0.0üreten xdışında, xbir -0.0: Bu durumda biz toplamı sıfırdır ters işaretli iki işlenen bir miktar var ve §6.3 paragraf Bu eklemenin ürettiği 3 kural +0.0.
Yana +0.0değildir bit düzeyinde orijinal aynıdır -0.0ve bu -0.0girdi olarak oluşabilir meşru bir değerdir, derleyici potansiyel negatif sıfır dönüştürecek bu kodu koymak zorundadır+0.0 .
Özet: Varsayılan yuvarlama modunda, içinde x+0.0, eğerx
- değil
-0.0 , o zaman xkendisi kabul edilebilir bir çıktı değeridir.
- olduğu
-0.0 , daha sonra çıkış değeri olmalıdır +0.0 bitler aynı olmadığı, -0.0.
Çarpma Durumu
Varsayılan yuvarlama modunda , ile böyle bir sorun oluşmaz x*1.0. Eğer x:
- bir (alt) normal sayıdır,
x*1.0 == xher zaman .
- olduğu
+/- infinity, daha sonra sonucudur +/- infinityaynı işaretin.
olduğu NaNsonra göre,
IEEE 754 § 6.2.3 NaN Yayılımı
Bir NaN işlenenini sonucuna yayan ve giriş olarak tek bir NaN'ye sahip olan bir işlem, hedef biçiminde gösterilebiliyorsa, giriş NaN'nin yüküyle bir NaN üretmelidir.
bunlardan üs ve mantis (değil işareti) bu araçlar NaN*1.0vardır önerilen girişinden değişmemesini NaN. İşaret, yukarıdaki §6.3p1'e göre belirtilmemiştir, ancak bir uygulama bunun kaynak ile aynı olduğunu belirtebilir NaN.
- ise
+/- 0.0sonuç, §6.3p2 ile uyumlu olarak 0işaret biti 1.0ile XORed işaret biti ile bir olur. İşaret biti olduğu 1.0için 0, çıkış değeri girişten değişmez. Böylece, (negatif) sıfır x*1.0 == xolduğunda bile x.
Çıkarma Durumu
Varsayılan yuvarlama kipinde , çıkarma işlemi x-0.0de işlemsizdir çünkü eşdeğerdir x + (-0.0). Eğer xDİR
- bu durumda
NaN, §6.3p1 ve §6.2.3, toplama ve çarpma ile hemen hemen aynı şekilde uygulanır.
- olduğu
+/- infinity, daha sonra sonucudur +/- infinityaynı işaretin.
x-0.0 == xher zaman bir (alt) normal sayıdır .
- bir
-0.0"O §6.3p2 ile biz, [...], veya bir fark X bir toplamın işareti - olarak y toplamı x + (y), addends' işaretleri en az biri farklıdır; ". Bu bizi -0.0sonuç olarak atamaya zorlar (-0.0) + (-0.0), çünkü -0.0işarette hiçbir eklentiden farklıyken, +0.0işaret ikiden farklıdır. Bu maddeye aykırı olarak addends arasında.
- olduğunu
+0.0, o zaman bu ekleme duruma düşürür (+0.0) + (-0.0)yukarıda kabul İlavesi Durumunda §6.3p3 tarafından vermeye almaması nedeniyle, +0.0.
Tüm durumlar için girdi değeri çıktı olarak yasal olduğundan x-0.0, x == x-0.0işlemsiz ve totolojinin dikkate alınmasına izin verilir .
Değeri Değiştiren Optimizasyonlar
IEEE 754-2008 Standardı aşağıdaki ilginç alıntıya sahiptir:
IEEE 754 § 10.4 Birebir anlam ve değer değiştiren optimizasyonlar
[...]
Aşağıdaki değer değiştiren dönüşümler, diğerlerinin yanı sıra, kaynak kodun gerçek anlamını korur:
- X sıfır olmadığında ve bir sinyal NaN olmadığında ve sonuç x ile aynı üsse sahip olduğunda, 0 + x kimlik özelliğini uygulamak.
- X bir sinyal NaN olmadığında ve sonuç x ile aynı üsse sahip olduğunda 1 × x kimlik özelliğini uygulamak.
- Sessiz bir NaN'nin yükünü veya işaret bitini değiştirme.
- [...]
Tüm NaN'ler ve tüm sonsuzluklar aynı üssü paylaştığından x+0.0ve x*1.0sonlu için doğru yuvarlatılmış sonuç xtam olarak aynı büyüklüğe sahip xolduğundan, üsleri aynıdır.
sNaNs
Sinyalizasyon NaN'leri kayan nokta tuzak değerleridir; Kayan noktalı işlenen olarak kullanılması geçersiz bir işlem istisnasına (SIGFPE) neden olan özel NaN değerleridir. Bir istisnayı tetikleyen bir döngü optimize edilmiş olsaydı, yazılım artık aynı şekilde davranmazdı.
Bununla birlikte, user2357112'nin yorumlarda işaret ettiği gibi, C11 Standardı, NaN'lerin ( sNaN) sinyalizasyonunun davranışını açıkça tanımsız bırakır , böylece derleyicinin bunların meydana gelmediğini varsaymasına izin verilir ve böylece ortaya çıkan istisnalar da meydana gelmez. C ++ 11 standardı, NaN'leri işaretlemek için bir davranışı tanımlamaz ve bu nedenle onu tanımsız bırakır.
Yuvarlama Modları
Alternatif yuvarlama modlarında, izin verilen optimizasyonlar değişebilir. Örneğin, Round-to-Negative-Infinity modunda, optimizasyona x+0.0 -> xizin verilebilir, ancakx-0.0 -> x yasaklanır.
GCC'nin varsayılan yuvarlama modlarını ve davranışlarını üstlenmesini önlemek için deneysel bayrak -frounding-mathGCC'ye geçirilebilir.
Sonuç
Clang ve GCC , olsa bile -O3IEEE-754 uyumludur. Bu, IEEE-754 standardının yukarıdaki kurallarına uyması gerektiği anlamına gelir. x+0.0olduğu bit aynı değil için xtüm xbu kurallar altında, ama x*1.0 böyle olması tercih edilebilir : ne zaman, Yani
xBir NaN olduğunda , yükün değiştirilmeden geçirilmesi önerisine uyun .
- NaN sonucunun işaret bitini ile değiştirmeden bırakın
* 1.0.
- Zaman, işaret biti bir bölüm / ürün esnasında XOR emre itaat
xolduğunu değil bir NaN.
IEEE-754-güvenli olmayan optimizasyonu etkinleştirmek için (x+0.0) -> x, bayrağın -ffast-mathClang veya GCC'ye geçirilmesi gerekir.