Double veya float kullanmalı mıyım?


90

C ++ 'da birini diğerinin yerine kullanmanın avantajları ve dezavantajları nelerdir?


Kimse bir float dizisi ve bir double dizisi yapmayı denedi ve gerçekten float üzerindeki üyeler arasında 4 bayt ve çiftler üzerindeki üyeler arasında 8 bayt olup olmadığını gördü mü? 64 bitlik bir derleyicinin / bilgisayarın, çok fazla ihtiyacı olmasa bile kayan nokta için üye başına 8 bayt ayırması mümkündür.
user3015682

Yanıtlar:


104

Doğru cevabı öğrenmek istiyorsanız, Kayan Nokta Aritmetiği Hakkında Her Bilgisayar Bilimcisinin Bilmesi Gerekenler'i okumalısınız .

Kısacası, sunumunda daha yüksek hassasiyetedouble izin vermesine rağmen , belirli hesaplamalar için daha büyük hatalar üretecektir . "Doğru" seçim şudur: İhtiyaç duyduğunuz kadar hassas kullanın ancak daha fazlasını kullanmayın ve doğru algoritmayı seçin .

Çoğu derleyici "katı olmayan" modda genişletilmiş kayan nokta matematiği yapar (yani donanımda mevcut olan daha geniş bir kayan nokta türü kullanın, örneğin 80 bit ve 128 bit kayan), bu da dikkate alınmalıdır. Pratikte, hızda neredeyse hiç fark göremezsiniz - zaten bunlar donanımın temelidir.


10
Evet. Daha büyük ve daha büyük bellek parçalarını, paralel sayısal işlem birimlerini ve ardışık düzenlenmiş mimarileri önceden getiren modern CPU'larla, hız sorunu gerçekten bir sorun değil. Belki daha sayıların büyük miktarlarda, dikkatli davranmalıyız boyut 4 byte şamandıra ve 8 byte arasındaki fark çift olabilir bellek ayak izi bir fark yaratır.
lavinio

5
Well SSE (veya herhangi bir vertor kayan nokta birimi), çift kesinliğe kıyasla tek duyarlıkta iki kat daha fazla flop işleyebilecektir. Sadece x87 (veya herhangi bir skaler) kayan nokta yapıyorsanız, muhtemelen önemli olmayacaktır.
Greg Rogers

1
@Greg Rogers: Derleyiciler şu anda o kadar akıllı değil. Ham derleme yazmadığınız sürece, büyük farklılıkları yoktur. Ve evet, derleyici geliştikçe bu değişebilir.
J-16 SDiZ

Ek notlar: Verilerin neye benzediğine dair kesinlikle hiçbir fikriniz yoksa (veya bağlantılardaki tüm matematik bilgilerine dair hiçbir fikriniz yoksa), sadece kullanın double- çoğu durumda daha güvenlidir.
J-16 SDiZ

@jokoon, kayan noktada ve tüm hassas / sayısal kararlılık sorunu alanında basit bir şey yoktur.
vonbrand

45

Aksini yapmak için belirli bir nedeniniz olmadıkça, double kullanın.

Belki de şaşırtıcı bir şekilde, C (ve C ++ 'da) "normal" kayan nokta türü olan çifttir ve float değildir. Günah ve günlük gibi standart matematik işlevleri , argüman olarak çiftleri alır ve döndürme iki katına çıkar. Normal bir kayan nokta değişmez değeri, 3.14 yazarken olduğu gibi programınızda , double türüne sahiptir. Yüzer değil.

Tipik modern bilgisayarlarda, çiftler en az kayan hızlar kadar hızlı veya daha hızlı olabilir, bu nedenle performans, büyük hesaplamalar için bile genellikle dikkate alınması gereken bir faktör değildir. (Ve bunların büyük hesaplamalar olması gerekir, yoksa performans aklınıza bile girmemelidir. Yeni i7 masaüstü bilgisayarım bir saniyede altı milyar ikiye katlama yapabilir.)


26

Sorunun bağlamı olmadığı için bu sorunun yanıtlanması imkansızdır. İşte seçimi etkileyebilecek bazı şeyler:

  1. Float, double ve long double'ların derleyici uygulaması. C ++ standardı şu şekildedir:

    Üç kayan nokta türü vardır: float, double ve long double. Double tipi, en az float kadar hassasiyet sağlar ve uzun double tipi, en az double kadar hassasiyet sağlar.

    Dolayısıyla, üçü de aynı boyutta bellekte olabilir.

  2. Bir FPU'nun varlığı. Tüm CPU'ların FPU'ları yoktur ve bazen kayan nokta türleri taklit edilir ve bazen kayan nokta türleri desteklenmez.

  3. FPU Mimarisi. IA32'nin FPU'su dahili olarak 80bit'tir - 32 bit ve 64 bit kayan değerler, yükte 80bit'e genişletilir ve depoda azaltılır. Paralel olarak dört adet 32bit kayan veya iki adet 64bit kayan yapabilen SIMD de var. SIMD kullanımı standartta tanımlanmamıştır, bu nedenle SIMD'nin kullanılıp kullanılamayacağını belirlemek için daha karmaşık analizler yapan veya özel işlevlerin (kitaplıklar veya içsel) kullanımını gerektiren bir derleyici gerektirecektir. 80 bit dahili formatın sonucu, verilerin RAM'e ne sıklıkta kaydedildiğine bağlı olarak biraz farklı sonuçlar alabilmenizdir (dolayısıyla hassasiyeti kaybedersiniz). Bu nedenle, derleyiciler kayan nokta kodunu özellikle iyi optimize etmezler.

  4. Bellek bant genişliği. Bir çift, bir kayan noktadan daha fazla depolama gerektiriyorsa, verileri okumak daha uzun sürecektir. Bu saf cevap. Modern bir IA32'de, her şey verilerin nereden geldiğine bağlıdır. L1 önbelleğindeyse, verilerin tek bir önbellek hattından gelmesi koşuluyla yük ihmal edilebilir. Birden fazla önbellek satırını kapsıyorsa, küçük bir ek yük vardır. L2'den geliyorsa, biraz daha uzun sürer, RAM'deyse daha uzun sürer ve nihayet, diskte ise çok büyük bir zaman. Dolayısıyla float veya double seçimi, verilerin kullanılma biçiminden daha az önemlidir. Çok sayıda sıralı veri üzerinde küçük bir hesaplama yapmak istiyorsanız, küçük bir veri türü tercih edilir. Küçük bir veri kümesi üzerinde çok fazla hesaplama yapmak, herhangi bir önemli etkiye sahip daha büyük veri türlerini kullanmanıza olanak tanır. Eğer sen' verilere çok rastgele erişilirse, veri boyutu seçimi önemsizdir - veriler sayfalara / önbellek satırlarına yüklenir. Dolayısıyla, yalnızca RAM'den bir bayt isteseniz bile, 32 bayt aktarabilirsiniz (bu, sistemin mimarisine çok bağlıdır). Tüm bunlara ek olarak, CPU / FPU süper skaler (diğer adıyla ardışık düzenlenmiş) olabilir. Bu nedenle, bir yük birkaç döngü sürse bile, CPU / FPU, yükleme süresini bir dereceye kadar gizleyen başka bir şey (örneğin bir çarpma) yapmakla meşgul olabilir.

  5. Standart, kayan nokta değerleri için herhangi bir özel formatı zorlamaz.

Bir spesifikasyonunuz varsa, bu sizi en uygun seçeneğe yönlendirecektir. Aksi takdirde, ne kullanılacağı konusunda deneyim yaşanır.


16

Double daha kesindir, ancak 8 bayta kodlanmıştır. float yalnızca 4 bayttır, dolayısıyla daha az alan ve daha az hassasiyettir.

Uygulamanızda duble ve float varsa çok dikkatli olmalısınız. Geçmişte bundan dolayı bir sorun yaşadım. Kodun bir kısmı float kullanırken, kodun geri kalanı double kullanıyordu. Double'ı float'a ve ardından float'ı ikiye kopyalamak, büyük etkiye sahip olabilecek hassas hatalara neden olabilir. Benim durumumda, bir kimya fabrikasıydı ... umarım dramatik sonuçları olmamıştır :)

Sanırım bu tür bir hata yüzünden Ariane 6 roketi birkaç yıl önce patladı !!!

Bir değişken için kullanılacak tür hakkında dikkatlice düşünün


3
Float / double için 4/8 bayt garanti edilmez, platforma bağlı olacaktır. Hatta aynı tip bile olabilir ...
sleske

2
Ariane 5 kod 16 bitlik işaretli tamsayı içine değeri 32,767 daha büyüktü 64 bit kayan nokta, dönüştürmek çalıştı. Bu, roketin kendi kendini imha etme sırasını başlatmasına neden olan bir taşma istisnası oluşturdu. Söz konusu kod, daha eski, daha küçük bir roketten yeniden kullanılan koddu.
cmwt

5

Ben kişisel olarak bazı darboğazlar görene kadar her zaman iki katına çıkıyorum. Sonra yüzdürmeye geçmeyi veya başka bir bölümü optimize etmeyi düşünüyorum


4

Bu, derleyicinin double'ı nasıl uyguladığına bağlıdır. Double ve float'ın aynı tür olması yasaldır (ve bazı sistemlerde geçerlidir).

Bununla birlikte, eğer gerçekten farklılarsa, asıl mesele hassasiyettir. Bir çift, boyut farkı nedeniyle çok daha yüksek bir hassasiyete sahiptir. Kullandığınız sayılar genellikle bir kayan nokta değerini aşacaksa, o zaman bir çift kullanın.

Birkaç kişi performans sorunlarından bahsetti. Bu, düşünceler listemdeki sonuncu olurdu. Doğruluk, 1 numaralı düşünceniz olmalıdır.



2

Sanırım farklılıklar ne olursa olsun (herkesin işaret ettiği gibi, yüzer daha az yer kaplar ve genel olarak daha hızlıdır) ... hiç kimse double kullanarak performans sorunları yaşar mı? Çift kullan diyorum ... ve daha sonra "vay, bu gerçekten yavaş" diye karar verirseniz ... performans darboğazınızı bulun (muhtemelen iki katı kullandığınız gerçek değildir). O ZAMAN, sizin için hala çok yavaşsa, biraz hassasiyeti nerede feda edebileceğinizi görün ve şamandırayı kullanın.



1

Büyük ölçüde CPU'ya bağlıdır, en belirgin değiş tokuşlar hassasiyet ve bellek arasındadır. GB RAM ile bellek çok fazla sorun teşkil etmez, bu nedenle genellikle doubles kullanmak daha iyidir .

Performans gelince, büyük ölçüde CPU'ya bağlıdır. floats genellikle double32 bitlik bir makinede olduğundan daha iyi performans alır . 64 bit'te, double(genellikle) yerel boyut olduğundan s bazen daha hızlıdır. Yine de, veri türü seçiminizden çok daha önemli olan şey, işlemcinizdeki SIMD talimatlarından yararlanıp yararlanamayacağınızdır.


0

double daha yüksek hassasiyete sahipken, kayan değerler daha az bellek kullanır ve daha hızlıdır. Genel olarak, yeterince doğru olmadığı bir durumunuz yoksa float kullanmalısınız.


5
Tipik modern bilgisayarlarda çift, float kadar hızlıdır.
Thomas Padron-McCarthy
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.