5

Dün ben bir kayan noktalı aritmetik doğruluğunu kaybetme nedeni ile ilgili question istedi. X87 kayıtlarında tutulan ara sonuçlardan nasıl kaynaklandığına dair bir cevap aldım. Bu yardımcı oldu ama bazı detaylar hala kaçıyor. Bir önceki soruda sunduğum programın bir varyasyonu, debug modunda VC++ 2010 Express kullanıyorum.Yüzer nokta doğruluğu tekrar

int main() 
{ 
    double x = 1.8939201459282359e-308; /* subnormal number */ 
    double tiny = 4.9406564584124654e-324; /* smallest IEEE double */ 
    double scale = 1.6; 
    double temp = scale*tiny; 
    printf("%23.16e\n", x + temp); 
    printf("%23.16e\n", x + scale*tiny); 
} 

Bu ilk değer, IEEE standardına göre doğru

1.8939201459282369e-308 
1.8939201459282364e-308 

verir. scale değişkeninin 2.0 değerini vermesi, her iki hesaplama için de doğru değeri verir. İlk hesaplamada temp'un normal olmayan bir değer olduğunu ve dolayısıyla hassasiyeti kaybettiğini anlıyorum. Ayrıca, scale*tiny'un değerinin, daha büyük bir üs aralığı olan bir x87 registerında tutulduğunu ve bu değerin temp'dan daha hassas olduğunu anlıyorum. Anlamadığım şey, değeri x'a eklerken, düşük hassasiyet değerinden doğru cevabı almamızdır. Şüphesiz daha düşük bir doğruluk değeri doğru cevabı verebiliyorsa, daha yüksek bir doğruluk değeri de doğru cevabı vermelidir? Bu 'çift yuvarlama' ile ilgisi var mı?

Şimdiden teşekkürler, bu benim için yepyeni bir konu, bu yüzden biraz mücadele ediyorum.

+0

Aşağıdakiler doğru olabilir ama benim için hiç de açık değil: * Doğru bir yanıt verebiliyorsa daha doğru bir doğruluk değeri verilebiliyorsa, daha yüksek bir doğruluk değeri de doğru cevap vermelidir? * – NPE

+0

Bu hesaplamalarda 'uzun çifte' kullanırdım ... –

+0

Düşük hassasiyet sayısının son basamağında rastgele bir değere sahip olmadığını nasıl anlarız? Beklenene her zaman% 10'luk bir şans verilir. –

cevap

7

noktası daha büyük bir üs aralığına bağlı olarak, iki sayının x87 temsil normalin altında olmamasıdır. IEEE754 temsilciliğinde

,
x = 0.d9e66553db96f × 2^(-1022) 
tiny = 0.0000000000001 × 2^(-1022) 

ama x87 temsilinde

, 1.6*tiny IEEE754 temsilinde hesaplanır zaman en yakın zamandır beri Şimdi, bu 0.0000000000002 × 2^(-1022) yuvarlanır

x = 1.b3cccaa7b72de × 2^(-1023) 
tiny = 1.0000000000000 × 2^(-1074) 

matematiksel sonuca temsil edilebilir sayı.

0.d9e66553db96f × 2^(-1022) 
+ 0.0000000000002 × 2^(-1022) 
----------------------------- 
    0.d9e66553db971 × 2^(-1022) 

ama x87 temsil edilene x sonuçlar ekleme 1.6*tiny

1.999999999999a × 2^(-1074) 

olur ve bu

1.b3cccaa7b72de × 2^(-1023) 
+ 0.0000000000003333333333334 × 2^(-1023) 
----------------------------------------- 
    1.b3cccaa7b72e1333333333334 × 2^(-1023) 

53 önemli bit yuvarlanır sonucu eklendiğinde

olduğu
1.b3cccaa7b72e1 × 2^(-1023) 
01 significand 1. En son bit

iki bitişik gösterilebilir sayı 0.d9e66553db970 × 2^(-1022) arasında tam olarak yarı yolu olan o zaman, (bu normalden düşük sayı olduğu için bu significand en fazla 52 bit olabilir) IEEE-754 gösterimine dönüştürülürse ve 0.d9e66553db971 × 2^(-1022), varsayılan olarak sıfır ve sonuncu bit ile bire yuvarlanır.

FPU, anlamlılık için yalnızca 53 biti kullanacak şekilde yapılandırılmadıysa, ancak x87 uzatılmış hassaslık türünün tam 64'ü yapılandırılmamışsa, ekleme sonucunun IEEE754 sonucu 0.d9e66553db971 × 2^(-1022)'a daha yakın olacağını ve bu nedenle buna yuvarlanacağını unutmayın. .

Etkili bir şekilde, x87 gösterimi daha büyük bir üslup aralığına sahip olduğundan, IEEE754-altnormal sayıların anlamları için IEEE754 gösterimindeki anlamlardan daha fazla bite sahip olursunuz. Böylece, hesaplama sonucunun x87'de IEEE754'tekinden daha önemli bir yanı vardır.

+0

Teşekkürler Daniel, işlenmiş bir örnek ** gerçekten neye ihtiyacım vardı. Yani 1.b3cccaa7b72e1 × 2^(- 1023) IEEE-754'e dönüştürüldüğünde 0.d9e66553db971 × 2^(- 1022) yerine 0.d9e66553db970 × 2^(- 1022) yerine yuvarlanır. Genel olarak bu işlem için yuvarlama modu nedir? – john

+0

Sağ. ("Printf" için IEEE754'e yuvarlanmış olup olmadığımı bilmese de, "printf" de x87 gösterimini kullanabilir.) IEEE754'teki varsayılan yuvarlama modu yuvarlak bağlar, hatta son bittir önemi ve sıfır. –

+1

Merhaba Daniel, küçük bir açıklama: x87'de eklemeyi anlattığınız şekilde, "anlamlı bitlerin kısıtlanması nedeniyle", 0.0000000000003 × 2^(- 1023) "Cray eklentisi (http: //cs.nyu) gibi geliyor .edu/courses/fall03/G22.2420-001/lec4.pdf). X87'in yerine, tam olarak (1b3cccaa7b72e1333333333334 × 2^(- 1023)) ve sonra yuvarlama hesaplanması eşdeğerdir. –