Hayır, bu başka bir "Neden (1 / 3.0) * 3! = 1" sorusu değil.
Son zamanlarda kayan noktalar hakkında çok şey okudum; özellikle, aynı hesaplamanın farklı mimarilerde veya optimizasyon ayarlarında nasıl farklı sonuçlar verebileceği .
Bu, tekrarları depolayan veya eşler arası ağa bağlı (sunucu-istemcinin aksine) video oyunları için bir sorundur , bu da programı her çalıştırdıklarında tam olarak aynı sonuçları üreten tüm istemcilere güvenir - birinde küçük bir tutarsızlık kayan nokta hesaplama farklı makinelerde çok farklıydı oyun durumuna yol açabilir (hatta veya aynı makinede! )
Bu , IEEE-754'ü "takip eden" işlemciler arasında bile olur , çünkü bazı işlemciler (x86) çift genişletilmiş hassasiyet kullanır . Yani, tüm hesaplamaları yapmak için 80 bit kayıt kullanırlar, daha sonra 64 veya 32 bit olarak kesilirler, bu da hesaplamalar için 64 veya 32 bit kullanan makinelerden farklı yuvarlama sonuçlarına yol açar.
Bu sorun çevrimiçi birkaç çözüm gördüm, ama tüm C ++, C # için:
- (Windows), (Linux?) Veya (BSD)
double
kullanarak çift genişletilmiş kesinlik modunu devre dışı bırakın (tüm hesaplamalar IEEE-754 64 bit kullanır )._controlfp_s
_FPU_SETCW
fpsetprec
- Her zaman aynı derleyiciyi aynı optimizasyon ayarlarıyla çalıştırın ve tüm kullanıcıların aynı CPU mimarisine sahip olmasını gerektirir (platformlar arası oynama yok). Benim "derleyici" aslında program her çalıştırıldığında farklı optimize edebilir JIT olduğundan, bunun mümkün olduğunu düşünmüyorum.
- Sabit noktalı aritmetik kullanın
float
vedouble
tamamen ve kaçının .decimal
bu amaçla çalışır, ancak çok daha yavaş olur ve hiçbirSystem.Math
kütüphane işlevi bunu desteklemez.
Peki, bu bile C # bir sorun mu? Ya sadece Windows'u desteklemeyi amaçlıyorsam (Mono'yu değil)?
Eğer öyleyse, programımı normal çift hassasiyette çalışmaya zorlamanın bir yolu var mı?
Değilse, kayan nokta hesaplamalarının tutarlı kalmasına yardımcı olacak herhangi bir kütüphane var mı?
strictfp
tüm hesaplamaları genişletilmiş boyuttan ziyade belirtilen boyutta ( float
veya double
) yapılmaya zorlayan bir anahtar kelimeye sahiptir . Ancak Java'nın hala IEE-754 desteği ile ilgili birçok sorunu var. Çok (çok, çok) az programlama dili IEE-754'ü iyi destekler.