Ne zaman şamandıra kullanıyorsunuz ve ne zaman çift kullanıyorsunuz?


194

Programlama deneyimimde sık sık, gerçek sayılarım için float mı yoksa double mı kullanmam gerektiğine karar vermem gerekiyor. Bazen yüzmeye giderim, bazen çift giderim, ama bu gerçekten daha öznel hissettirir. Kararımı savunmakla karşı karşıya kalırsam, muhtemelen sağlam sebepler vermem.

Ne zaman float kullanıyorsunuz ve ne zaman çift kullanıyorsunuz? Her zaman iki katı kullanır mısın, sadece hafıza kısıtlamaları varsa, yüzmeye gidersin? Ya da hassas gereklilik iki kez kullanmanızı gerektirmediği sürece daima yüzer mi kullanıyorsunuz? Float ve çift arasındaki temel aritmetiklerin hesaplama karmaşıklığı ile ilgili bazı önemli farklılıklar var mı? Float veya double kullanmanın avantajları ve dezavantajları nelerdir? Ve uzun süredir çift kullandın mı?


28
Pek çok durumda, ikisini de kullanmak yerine ondalık kayan veya sabit nokta türünü kullanmak istersiniz. İkili kayan nokta türleri çoğu ondalık sayıyı tam olarak gösteremez.
CodesInChaos

3
İlgili nokta yuvarlama hatalarını yüzen nedeni nedir? . @CodesInChaos cevabım, bu seçimi yapmanıza yardımcı olacak kaynaklar önerir, tek bedene uyan hiçbir çözüm yoktur.
Mark Booth

Çok iyi cevap bulundu: Stack Overflow
Haris

5
Tam olarak "ondalık" ile ne demek istiyorsun? 0.01 gibi değerleri tam olarak (para için söylemek gibi) temsil etmeniz gerekiyorsa, o zaman (ikili) kayan nokta cevap değildir. Yalnızca tam sayı olmayan sayılar anlamına geliyorsa, o zaman kayan nokta büyük olasılıkla iyidir - ancak sonra "ondalık sayılar" neye ihtiyacınız olduğunu tanımlamak için en iyi kelime değildir.
Keith Thompson,

1
Her zaman bir seçeneğin yok. Örneğin, Arduino platformunda, hem çift hem de yüzer yüzmeye eşittir. Gerçek çiftleri işlemek için bir eklenti kütüphanesi bulmanız gerekir.
kiwiron

Yanıtlar:


187

Kayan nokta türü için varsayılan seçenek olmalıdır double. Bu aynı zamanda bir eki olmadan ya da (örneğin kayan nokta sayıları üzerinde işlem standart fonksiyonlar (C) kayan nokta değişmezleri ile elde türüdür exp, sinvs.).

float sadece çok sayıda kayan nokta üzerinde çalışmanız gerekiyorsa (binlerce veya daha fazla sırasına göre düşünün) kullanılmalı ve algoritmanın analizi, azaltılmış aralığın ve hassasiyetin sorun yaratmadığını göstermiştir.

long double'dan daha fazla menzil veya kesinlik gerekiyorsa doubleve bunu hedef platformunuzda sağlıyorsa kullanılabilir.

Özet olarak floatve "her gün" kullanım için long doubleuzmanlar tarafından kullanılmak üzere ayrılmalıdır double.


10
Kayan nokta önbelleğe alma ve veri aktarımıyla ilgili bir performans sorunu olmadığı sürece muhtemelen birkaç bin değerlik bir kaymayı düşünmezdim. Şamandıranın yeterince kesin olduğunu göstermek için analiz yapmanın genellikle önemli bir maliyeti vardır.
Patricia Shanahan,

4
Zeyilname olarak, diğer sistemlerle uyumluluğa ihtiyacınız varsa, aynı veri tiplerini kullanmak avantajlı olabilir.
zzzzBov

15
Milyonlarca numara için yüzer numara kullanırdım, 1000'ler için değil. Ayrıca, bazı GPU'lar yüzdürme işlemlerini daha iyi yapar, bu özel durumda yüzdürme kullanımı. Başka, dediğiniz gibi, çift kullanın.
user949300,

4
@PatriciaShanahan - 'ile ilgili performans problemi ...' İyi bir örnek, SSE2 veya benzeri bir vektör talimatı kullanmayı planlıyorsanız, floatta 4 ops / vector (çift başına vs 2) yapabilir; yarısı ops yarısı ve yarısı okumak ve yazmak için veri). Bu, şamandıraların kullanılmasının çekici hale geldiği eşiği önemli ölçüde azaltabilir ve sayısal sorunları çözme konusunda zahmete değer.
greggo

12
Bu cevabı ek bir tavsiye ile onaylıyorum: Biri ekran için RGB değerleri ile çalışırken float, insan gözü, ekran veya renk sistemi ne kadar fazla hassasiyete sahip olmadığından, kullanımı kabul edilebilir (ve bazen yarı-hassas) . Bu tavsiye OpenGL vb. İçin geçerlidir. Bu ilave tavsiye, daha katı hassasiyet gerektiren tıbbi görüntüler için geçerli değildir.
saat

42

Modern bilgisayarları hedef alan çift kod yerine float kullanımının nadiren nedeni vardır. Ekstra hassasiyet, yuvarlama hatalarını veya sorunlara neden olan diğer yanlışlıkları olasılığını azaltır (ancak ortadan kaldırmaz).

Şamandıra kullanmayı düşünebilmemin ana nedenleri:

  1. Büyük sayı dizileri saklıyorsunuz ve programınızın bellek tüketimini azaltmanız gerekiyor.
  2. Doğal olarak çift duyarlıklı kayan noktaları desteklemeyen bir sistemi hedefliyorsunuz. Yakın zamana kadar birçok grafik kartı yalnızca tek bir hassas kayan noktaları destekledi. Sınırlı kayan nokta desteğine sahip çok sayıda düşük güçlü ve gömülü işlemci olduğundan eminim.
  3. Tek duyarlığın çift hassasiyetten daha hızlı olduğu donanımı hedefliyorsunuz ve uygulamanız kayan nokta aritmetiğini yoğun olarak kullanıyor. Modern Intel işlemcilerde tüm kayan nokta hesaplamalarının çifte hassasiyette yapıldığına inanıyorum, bu yüzden burada hiçbir şey kazanmıyorsunuz.
  4. Düşük seviyeli optimizasyon yapıyorsunuz, örneğin bir seferde birden fazla numara üzerinde çalışan özel CPU talimatlarını kullanarak.

Bu nedenle, temel olarak, donanım kısıtlamalarınız yoksa ya da analiz, çift duyarlıklı sayıları kaydetmenin bellek kullanımına önemli bir katkı sağladığını göstermediği sürece iki katıdır.


2
Intel x86 işlemciler anlamına gelen "Modern bilgisayarlar". Eskilerin kullandığı makinelerden bazıları temel şamandıra tipiyle mükemmel bir hassasiyet sağlıyordu. (CDC 6600, 60 bitlik bir kelime, 48 bit normalleştirilmiş kayan noktalı mantis, 12 bit üstel kullandı. Bu,
x86'nın

@ John.R.Strohm: kabul etti, ancak C derleyicileri CDC6600'de yoktu. Fortran
IV'dü

"Modern bilgisayarlar" ile IEEE kayan nokta standardı yaygın olarak uygulandığı için son on yıl veya iki yıl içinde inşa edilmiş herhangi bir işlemciyi kastediyorum. X86 olmayan mimarilerin var olduğunu ve bunun cevabımı akılda tuttuğunu mükemmel bir şekilde biliyorum - tipik olarak x86 olmayan GPU'lardan ve yerleşik işlemcilerden bahsettim.
user611910

Ancak bu doğru değil. SSE2, bir işlemde 4 yüzer veya 2 çift değiştirebilir, AVX 8 yüzer veya 4 çift değiştirebilir, AVX-512 16 yüzer veya 8 çift değiştirebilir. Her türlü yüksek performanslı bilgi işlem için, yüzdürme matematiği, x86'da iki katına çıkan işlemlerin iki katı hızda düşünülmelidir.
Larry Gritz

1
Ve bundan daha da kötüsü, çünkü işlemcinin önbelleğine iki kat daha fazla yüzebildiğiniz kadar iki kat sığabiliyorsunuz ve bellek gecikmesi birçok programdaki ana tıkanıklık olabilir. Çalışmakta olan bütün bir yüzdürme kümesini önbellekte sıcak tutmak, kelimenin tam anlamıyla, çift kullanmaktan ve RAM'e dökülmelerinden daha hızlıdır.
Larry Gritz

10

doubleTüm hesaplamalar ve geçici değişkenler için kullanın . floatBir dizi numara tutmanız gerektiğinde kullanın - float[](eğer hassasiyet yeterliyse) ve on binlerce floatnumara ile uğraşıyorsunuzdur .

Çoğu / çoğu matematik işlevi veya işleç dönüştürür / döndürür doubleve floatherhangi bir ara adım için sayıları geri çevirmek istemezsiniz .

Örneğin, bir dosya veya akıştan 100.000 sayı girişi varsa ve bunları sıralamanız gerekiyorsa, sayıları a float[].


5

Bazı platformlar (ARM Cortex-M2, Cortex-M4 vb.) Çift desteklemiyor (İşlem kılavuzunun referans kılavuzunda her zaman kontrol edilebilir. Derleme uyarıları veya hataları yoksa, kodun optimal olduğu anlamına gelmez. çift taklit edilebilir.). Bu yüzden int ya da yüzmeye devam etmeniz gerekebilir .

Aksi takdirde çift kullanırdım .

Ünlü makaleyi D. Goldberg ("Her Bilgisayar Bilim Adamının Kayan Nokta Aritmetiği Hakkında Bilmeniz Gerekenleri") tarafından kontrol edebilirsiniz. Kayan noktalı aritmetik kullanmadan önce iki kere düşünmelisiniz. Kendi durumunuzda hiç ihtiyaç duyulmadıkları oldukça büyük bir şans.

http://perso.ens-lyon.fr/jean-michel.muller/goldberg.pdf


3
Bu soru zaten bir yıl önce çok iyi cevaplandı ... ama her durumda, iki katı FPU hızlandırma ile platformlarda iki kez kullandığın her zaman, her ne şekilde olursa olsun, başka bir yerde kullanman gerektiğini söylemeliyim. derleyicinin yalnızca kayan noktalı bir FPU'dan faydalanmak yerine öykünmesini sağlamak (FPU'ların tüm platformlarda da gerekli olmadığına dikkat edin, aslında bir Cortex-M4 mimarisi onları isteğe bağlı bir özellik olarak tanımlar [M2 bir yazım hatası mıydı?] ).
Selali Adobor,

Bu mantığın anahtarı, gerçek olanın kayan nokta aritmetiğinden bıkmış olması gerektiği ve birçok "tuhaf" olması gerektiği, kayan nokta yerine sadece çift kullanım anlamına gelen çiftler için FPU desteğinin varlığını kesinlikle almaması. Şamandıralar genelde iki kat daha hızlıdır ve daha az hafıza alır (FPU özellikleri değişir). Kullanım hacmi, bu noktanın erken optimizasyonda olmasını engeller. Gerçek şu ki, çiftler açıkça bir çok (belki de çoğu) uygulamalar için overkill. Bu sayfadaki öğelerin gerçekten göreli konumlarına ve boyutlarına 13 ondalık basamağa hesaplanması gerekiyor mu?
Selali Adobor,

2
Site dışı bir sayfaya veya belgeye bir bağlantı eklerken, lütfen ilgili bilgileri veya özeti belgeden cevabınıza kopyalayın. Site dışı bağlantıların zaman içinde kaybolma eğilimi vardır.
Adam Zuckerman

3

Gerçek dünyadaki problemler için bu soruyu cevaplarken verilerinizin örnekleme eşiği önemlidir. Benzer şekilde, gürültü tabanı da önemlidir. Veri türü seçiminizden herhangi birini aşarsanız, artan hassasiyetten hiçbir fayda gelmez.

Çoğu gerçek dünya örnekleyicisi 24 bit DAC s ile sınırlıdır. Gerçek dünya hesaplamalarında 32 bit hassasiyetin, 24 hassasiyetin önemli olduğu yerlerde yeterli olması gerektiğini ileri sürün.

Çift hassasiyet, 2x bellek maliyeti ile geliyor. Bu nedenle çiftler üzerinde yüzerlerin kullanımını sınırlamak çalışan uygulamaların bellek ayak izini / bant genişliğini büyük ölçüde azaltabilir.


-3

Float ve double arasında hangi değişkenin kullanılacağının seçimi, gereken verilerin doğruluğuna bağlıdır. Bir cevabın gerçek cevabın önemsiz farkına sahip olması gerekiyorsa, gereken ondalık basamak sayısı çok olacaktır, bu nedenle kullanımda olması için iki katı olacaktır.


3
Bu cevap soruya yeni bir şey eklemez ve fiili kullanım için hiçbir şey söylemez.
Martijn Pieters

-5

Genellikle, floatçok fazla ihtiyaç duymadığım zamanları kullanırım - örneğin, para için - bu yanlış, ama yanlış kullanmaya alışkınım.

Öte yandan, doubleörneğin karmaşık matematiksel algoritmalar için daha fazla kesinlik gerektiğinde kullanırım.

C99 standardı şöyle diyor:

Üç kayan nokta tipi vardır: şamandıra, çift ve uzun çift. Double type en az kayan nokta kadar hassaslık sağlar ve long double türü en az iki katı kadar hassasiyet sağlar. Float türündeki değer kümesi, double türündeki değer kümesinin bir alt kümesidir; double türünün değer kümesi, long double türünün değer kümesinin bir alt kümesidir.

Hiç long doublekullanmadım ama C / C ++ 'ı fazla kullanmam. Genellikle, Python gibi dinamik olarak yazılmış dilleri kullanırım, burada türleri umursamamanız gerekir.

Double vs Float hakkında daha fazla bilgi için bu soruya SO'da bakın .


25
Ciddi para hesaplamaları için kayan nokta kullanmak muhtemelen bir hatadır.
Bart van Ingen Schenau

17
şamandıra para için tam olarak yanlış türüdür. Mümkün olan en yüksek hassasiyeti kullanıyor olmanız gerekir.
ChrisF

8
@BartvanIngenSchenau Para için kayan nokta genellikle tamamdır, ikili kayan nokta değildir. Örneğin .net Decimalbir kayan nokta türüdür ve genellikle para hesaplamaları için iyi bir seçimdir.
CodesInChaos

13
@ChrisF Para için "yüksek hassasiyete" ihtiyacınız yok, kesin değerlere ihtiyacınız var.
Sean McSomething

2
@SeanMcSomething - Adil nokta. Bununla birlikte, yüzdürmeler yine de yanlış tiptedir ve çoğu dilde mevcut olan yüzer nokta tipleri göz önüne alındığında, "kesin değerler" elde etmek için "yüksek hassasiyete" ihtiyacınız vardır.
ChrisF
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.