Java'da kayan ve çift veri türü


220

Kayan veri türü, tek duyarlıklı 32 bitlik IEEE 754 kayan noktadır ve çift veri türü, çift duyarlıklı 64 bitlik IEEE 754 kayan noktadır.

Bu ne demek? Ve ne zaman çift yerine float kullanmalıyım?


8
Bellek kullanımı kritik olduğunda çift yerine float kullanmalısınız. Daha kesin hesaplamalara ihtiyacınız varsa, iki katını kullanın.
Everv0id

12
@ Everv0id: Hafızanın o kadar dar olduğu bir durumdan emin değilim ki, alan için doğruluğu feda etmek zorunda kaldı. ( İyilik uğruna Java kullanıyorsun ...) İstendiğinde bazı durumlar olabilir, ama benim pratiğimde bunu nadiren gördüm. Bunun neden iyi bir fikir olduğuna inandığınız hakkında ayrıntılı bilgi edinmek isterseniz, örneğin bir yanıtı vermek değerli bir ek olacaktır.
Makoto


5
@Makoto aslında, hiç şamandıra kullanmadım, sadece iki katına çıktı. Ancak, büyük miktarlarda kayan nokta sayısı tutması gereken uygulamalar (teoride) olabilir, bu nedenle 2x bellek kullanımı kritik olabilir. Teorik olarak, ofc; pratikte her zaman başka bir sunucu satın alabilirsiniz .
Everv0id

3
Hafızadan tasarruf etmek için 4 bayt ve hatta 2 bayt sabit hassas sayılar kullandım, ancak bunlardan milyarlarcaınız yoksa buna değmez. Eğer (bir kere daha mektup vardır) yerine "şamandıra" nin "çift" yazmak için gereken zamanı değer 1000x daha kullandığınız ekstra bellek daha ama kullanılıyorsa doubleziyade floathassas ilgili hata kurtarır, buna değer öyle .
Peter Lawrey

Yanıtlar:


259

Üzerinde bulunan Wikipedia sayfası iyi bir başlangıç ​​noktasıdır.

Sonuç olarak:

  • float32 bit, 1 işaret biti, 8 bit üs ve 23 bit anlamlılık (veya bilimsel gösterim numarasından sonra gelen: 2.33728 * 10 12 ; 33728 anlamlıdır) ile temsil edilir.

  • double 64 bit, 1 işaret biti, 11 bit üs ve 52 bit anlamlı olarak temsil edilir.

Varsayılan olarak, Java kullanan doubleonun kayan noktalı sayılar temsil etmek (yani edebi 3.14is Yazılan double). Aynı zamanda size çok daha büyük bir sayı aralığı verecek olan veri türüdür, bu yüzden kullanımını kesinlikle teşvik ederim float.

Belirli aslında kullanımınızı zorlamak kütüphaneler olabilir float, ama genel olarak - Eğer sonuç sığacak kadar küçük olacağını garanti sürece float'ın öngörülen aralık , o zaman birlikte opt en iyisidir double.

Doğruluğa ihtiyacınız varsa - örneğin, yanlış (ondalık) bir ondalık değere sahip olamazsınız 1/10 + 2/10veya para birimiyle herhangi bir şey yapıyorsunuz (örneğin, sistemde 10,33 ABD Doları'nı temsil eden), ardından BigDecimalbir keyfi hassasiyet ve bu gibi durumları zarif bir şekilde ele alın.


4
Verilen örnekte 233728 == mantis değil mi? Demek istediğim, tamsayı kısmı başka nerede saklanıyor?
JaLoveAst1k

1
@ mathguy54: Bilimsel gösterimde, 2 tamsayı ve .33728 mantis olacaktır. İşte buna bir referans.
Makoto

5
Şamandıralar ve çiftler hakkında bilgi arıyordum ve bunu buldum ve yorum yapmam gerekiyordu: Kesirli sent içermeyen para birimi ile bir şey yapıyorsanız, BigDecimal kullanmak saçma. Ortak para birimi ayrık verilerdir, bu nedenle bir tamsayı veri türü kullanmalısınız. (Bu, genç programcılar tarafından yapılan daha yaygın hatalardan biridir - dolarları sentlerden ayırmak için a. Kullandığımızdan, bunun kayan nokta değeri olduğunu düşünüyorlar. Değil.)
Trixie Wolf

2
@TrixieWolf, daha spesifik olabilir misiniz, iki tamsayı (tamsayı ve ondalık kısımlar) kullanmayı önerdiniz mi? Ortak para biriminden bahsediyorsunuz, gerisi ne olacak? Bir miktar 6 ondalık ile değerlendirilir, böylece basitçe yapamazsınız *100. Lütfen, burada bir noktanız var ama daha kesin olabilir misiniz :)
AxelH

9
@AxelH Kesirli sentlerin bulunabileceği finansal hesaplamaların ortasında, para her zaman ayrıktır. Verileri saklamak için bir tamsayı türü kullanırsınız. Yani 5.34 $ 534 olarak saklanır. Dolar kısmı tamsayı matematikte val / 100'dür ve sentler tamsayı matematikte val% 100'dür, burada% kalan işlemdir. Ondalık değeri aşan daha fazla yeri olan para için, ayrık olduğu için hala ayrılmaz olarak saklanmalıdır. Ayrık olmasa bile, çoğu zaman ayrık bir depolama alanına geri dönmek isteyeceksiniz çünkü hassastır, böylece yuvarlama hatalarına para kaybetmeyeceksiniz.
Trixie Wolf

72

Bir şamandıra yaklaşık verir. 6-7 ondalık basamak hassasiyeti verirken bir çift size yakl. 15-16. Ayrıca sayı aralığı çift için daha büyüktür.

Bir çiftin 8 bayt depolama alanına ihtiyacı olurken, bir şamandıra sadece 4 bayta ihtiyaç duyar.


13

Gerçek sayılar olarak da bilinen kayan nokta sayıları, kesirli kesinlik gerektiren ifadeler değerlendirilirken kullanılır. Örneğin, kare kök gibi hesaplamalar veya sinüs ve kosinüs gibi aşkınlar, hassasiyeti kayan nokta türü gerektiren bir değer ile sonuçlanır. Java, kayan nokta türleri ve işleçlerinin standart (IEEE – 754) kümesini uygular. Sırasıyla tek ve çift kesinlikli sayıları temsil eden iki tür kayan nokta tipi vardır: float ve double. Genişlikleri ve aralıkları burada gösterilmiştir:


   Name     Width in Bits   Range 
    double  64              1 .7e308 to 1.7e+308
    float   32              3 .4e038 to 3.4e+038


şamandıra

Float türü, 32 bit depolama alanı kullanan tek duyarlıklı bir değer belirtir. Tek duyarlık bazı işlemcilerde daha hızlıdır ve çift duyarlıktan yarısı kadar yer kaplar, ancak değerler çok büyük veya çok küçük olduğunda kesin olmayacaktır. Şamandıra tipi değişkenler, kesirli bir bileşene ihtiyacınız olduğunda yararlıdır, ancak büyük bir hassasiyet gerektirmez.

Aşağıda bazı değişken değişken bildirimleri verilmiştir:

şamandıra yüksekliği, düşük sıcaklık;


çift

Çift anahtar kelime ile belirtildiği gibi çift kesinlik, bir değeri saklamak için 64 bit kullanır. Çift hassasiyet, yüksek hızlı matematiksel hesaplamalar için optimize edilmiş bazı modern işlemcilerde tek hassasiyetten daha hızlıdır. Sin (), cos () ve sqrt () gibi tüm aşkın matematik işlevleri çift değer döndürür. Birçok yinelemeli hesaplamada doğruluğu korumanız veya büyük değerli sayıları işlemeniz gerektiğinde, çift en iyi seçimdir.


Bu cevap şamandıra ve çift kullanmamız gerektiğinde net bir şekilde açıklığa kavuştu. Neden olmasın?
Ye Win

8
Java'da para birimi için floatne doubletürler ne de en iyi şekilde kullanılır, çünkü yuvarlama hataları için fırsat açarlar. Bu makale daha ayrıntılı olarak ele alınmıştır: javapractices.com/topic/TopicAction.do?Id=13
PPartisan

1
"şamandıra dolar ve sentleri temsil ederken yararlı olabilir." - hayır hayır Hayır Hayır Hayır Hayır Hayır. Asla, para birimini şamandıra / çift olarak asla saklamayın.
aktiviteyi azaltma

2

Bununla birlikte Java'nın hesaplamalar için double kullanmaya karşı bir önyargıya sahip olduğu görülmektedir:

Bugün daha önce yazdığım programın noktalarında, float kullandığımda yöntemler işe yaramadı, ancak float'ı (NetBeans IDE'de) çiftle değiştirdiğimde şimdi harika çalışıyor:

package palettedos;
import java.util.*;

class Palettedos{
    private static Scanner Z = new Scanner(System.in);
    public static final double pi = 3.142;

    public static void main(String[]args){
        Palettedos A = new Palettedos();
        System.out.println("Enter the base and height of the triangle respectively");
        int base = Z.nextInt();
        int height = Z.nextInt();
        System.out.println("Enter the radius of the circle");
        int radius = Z.nextInt();
        System.out.println("Enter the length of the square");
        long length = Z.nextInt();
        double tArea = A.calculateArea(base, height);
        double cArea = A.calculateArea(radius);
        long sqArea = A.calculateArea(length);
        System.out.println("The area of the triangle is\t" + tArea);
        System.out.println("The area of the circle is\t" + cArea);
        System.out.println("The area of the square is\t" + sqArea);
    }

    double calculateArea(int base, int height){
        double triArea = 0.5*base*height;
        return triArea;
    }

    double calculateArea(int radius){
        double circArea = pi*radius*radius;
        return circArea;
    }

    long calculateArea(long length){
        long squaArea = length*length;
        return squaArea;
    }
}

Bugün de aynı sorunu yaşadım. Bu yanlılığın ardındaki neden ne olabilir?
Shachi

2

Bu hata verecektir:

public class MyClass {
    public static void main(String args[]) {
        float a = 0.5;
    }
}

/MyClass.java:3: hata: uyumsuz türler: çiftten float float'a olası kayıplı dönüşüm a = 0.5;

Bu mükemmel bir şekilde çalışacaktır

public class MyClass {
    public static void main(String args[]) {
        double a = 0.5;
    }
}

Bu da mükemmel bir şekilde çalışacaktır

public class MyClass {
    public static void main(String args[]) {
        float a = (float)0.5;
    }
}

Sebep : Java, daha yüksek hassasiyet sağlamak için varsayılan olarak gerçek sayıları iki katına kaydeder.

Double, hesaplama sırasında daha fazla yer kaplar, ancak daha kesin ve float daha az yer kaplar, ancak daha az kesindir.


1

IEEE standartlarına göre, float gerçek sayının 32 bit gösterimidir, double ise 64 bit gösterimdir.

Java programlarında normalde çoğunlukla çift veri türünün kullanıldığını görürüz. Sadece çift veri tipi kullanılarak yerleştirilebilecek sayı aralığı, şamandıra kullanıldığında aralıktan daha fazla olduğu için taşmalardan kaçınmaktır.

Ayrıca yüksek hassasiyet gerektiğinde, çift kullanımı teşvik edilir. Uzun zaman önce uygulanan az sayıda kütüphane yöntemi hala şamandıra veri türünün bir zorunluluk olarak kullanılmasını gerektirmektedir (bu sadece şamandıra kullanılarak uygulandığı için başka bir şey değildir!).

Ancak, programınızın küçük sayılar gerektirdiğinden eminseniz ve şamandıra kullanımınızla birlikte taşma gerçekleşmezse, şamandıra kullanımı, şamandıraların çiftin gerektirdiği şekilde belleğin yarısını gerektirdiğinden alan karmaşıklığınızı büyük ölçüde artıracaktır.


0

Bu örnek, Java'daki bir kayan noktadan işaretin (en soldaki bit), üs (sonraki 8 bit) ve mantisin (en sağdaki 23 bit) nasıl ayıklanacağını gösterir.

int bits = Float.floatToIntBits(-0.005f);
int sign = bits >>> 31;
int exp = (bits >>> 23 & ((1 << 8) - 1)) - ((1 << 7) - 1);
int mantissa = bits & ((1 << 23) - 1);
System.out.println(sign + " " + exp + " " + mantissa + " " +
  Float.intBitsToFloat((sign << 31) | (exp + ((1 << 7) - 1)) << 23 | mantissa));

Aynı yaklaşım çiftler için de kullanılabilir (11 bit üs ve 52 bit mantis).

long bits = Double.doubleToLongBits(-0.005);
long sign = bits >>> 63;
long exp = (bits >>> 52 & ((1 << 11) - 1)) - ((1 << 10) - 1);
long mantissa = bits & ((1L << 52) - 1);
System.out.println(sign + " " + exp + " " + mantissa + " " +
  Double.longBitsToDouble((sign << 63) | (exp + ((1 << 10) - 1)) << 52 | mantissa));

Kredi bilgileri: http://sj.github.io/java-float/


0

Hassas hesaplamalar için float yerine double ve daha az doğru hesaplamalar kullanırken double yerine float kullanmalısınız. Kayan nokta yalnızca ondalık sayılar içerir, ancak çift IEEE754 çift kesinlikli kayar nokta sayısı içerir, bu da sayıların daha doğru bir şekilde tutulmasını ve hesaplanmasını kolaylaştırır. Bu yardımcı olur umarım.


0

Düzenli programlama hesaplamalarında float kullanmıyoruz. Sonuç aralığının kayan noktalı veri türü aralığında olduğundan emin olursak, bellek tasarrufu için bir kayan noktalı veri türü seçebiliriz. Genellikle, iki nedenden dolayı çift kullanırız:

  • Kayan nokta numarasını kayan nokta veri türü olarak kullanmak istiyorsak, yöntem arayanının açıkça F veya f sonekini eklemesi gerekir, çünkü varsayılan olarak her kayan nokta numarası çift olarak değerlendirilir. Programcının yükünü arttırır. Çift veri türü olarak kayan nokta sayısı kullanırsak, herhangi bir sonek eklememiz gerekmez.
  • Float, tek duyarlıklı bir veri türüdür, 4 bayt kapladığı anlamına gelir. Bu nedenle büyük hesaplamalarda tam bir sonuç elde edemeyiz. Çift veri türünü seçersek 8 bayt kaplar ve eksiksiz sonuçlar alırız.

Hem şamandıra hem de çift veri türleri özellikle yaklaşık hataların kabul edilebilir olduğu bilimsel hesaplamalar için tasarlanmıştır. Doğruluk en öncelikli konu ise, kayan nokta veya çift veri türü yerine BigDecimal sınıfının kullanılması önerilir. Kaynak: - Java'da float ve double datatypes

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.