0.0 ile 1.0 arasında kaç tane çift sayı vardır?


95

Bu yıllardır aklımda olan bir şey ama daha önce sormaya hiç zaman ayırmadım.

Birçok (sözde) rasgele sayı üreteci, 0.0 ile 1.0 arasında rasgele bir sayı üretir. Matematiksel olarak bu aralıkta sonsuz sayılar vardır, ancak doublebir kayan nokta sayısıdır ve bu nedenle sonlu bir kesinliğe sahiptir.

Yani sorular:

  1. double0.0 ile 1.0 arasında kaç sayı vardır?
  2. 1 ile 2 arasında sayı var mı? 100 ile 101 arasında mı? 10 ^ 100 ile 10 ^ 100 + 1 arasında mı?

Not: Bir fark yaratıyorsa, doubleözellikle Java'nın tanımıyla ilgileniyorum .

Yanıtlar:


68

Java doubles olan IEEE-754 , bu nedenle bunlar, 52-bit fraksiyonuna sahip, biçim; ikisinin herhangi iki bitişik gücü arasında (biri dahil ve bir sonrakini hariç), bu nedenle 2'den double52'ye kadar farklı s (yani bunların 4503599627370496'sı) olacaktır. Örneğin, bu, double0,5 dahil edilen ve 1,0 hariç tutulanlar arasındaki farklı URL'lerin sayısıdır ve tam olarak çoğu, 1,0 dahil edilen ve 2,0 hariç tutulan arasında yer alır vb.

doubles0.0 ile 1.0 arasında saymak, ikinin üsleri arasında bunu yapmaktan daha zordur, çünkü bu aralıkta ikinin birçok gücü vardır ve ayrıca, normal olmayan sayıların dikenli konularına girilir. Üslerin 11 bitinden 10'u söz konusu aralığı kapsıyor, bu nedenle normalleştirilmiş sayılar (ve sanırım birkaç tür NaN) dahil olmak üzere, ikinin doublekuvvetleri arasındaki s'nin 1024 katına sahip olacaksınız - en fazla 2**62toplamda . Normalize edilmemiş ve c hariç, sayımın 1023 katı olacağına inanıyorum 2**52.

"100 ila 100.1" gibi rastgele bir aralık için daha da zordur, çünkü üst sınır tam olarak a olarak gösterilemez double(ikinin herhangi bir kuvvetinin tam katı değildir). Kullanışlı bir yaklaşım olarak, ikinin üsleri arasındaki ilerleme doğrusal olduğundan, söz konusu aralığın, 0.1 / 64ikinin çevreleyen kuvvetleri (64 ve 128) arasındaki aralığın th olduğunu söyleyebilirsiniz , bu nedenle

(0.1 / 64) * 2**52

farklı doubles - 7036874417766.4004bir veya iki vermek veya almak ;-)


@Alex: 100 - 100.1 yazdığımda yanlış yazdım. 100 ila 101'i kastetmiştim. Temel olarak, keyfi N için N ve N + 1 arasında
poligenelubricants

4
@Alex: O halde şunu açıklığa kavuşturayım: 2**64mümkün olandan daha fazla çift ​​değer olamaz (çünkü bu 64 bitlik bir tür olduğundan) ve görünüşe göre bu değerlerin BÜYÜK bir oranı 0..1?
poligenel yağlayıcılar

9
@polygene, evet ve evet - özellikle olası değerlerin yaklaşık dörtte biri (herhangi bir "normal" kayan nokta için herhangi bir taban ve üs ve kesir uzunlukları için) 0,0 ile 1,0 arasındadır (1,0 ile sonsuz arasında başka bir çeyrek ve kalan yarısı gerçek eksenin negatif yarısında). Esasen, üssün değerlerinin yarısı (normal bir önyargı ile, aralığının yarısı dahilinde) tabanın negatif güçlerini temsil eder, bu nedenle <1.0 sayılar.
Alex Martelli 05

8
@polygenelubricants: Birçok uygulama için 0 ile 1 arasındaki aralık, 100 ile 101 arasındaki aralıktan çok, çok daha önemli ve ilginçtir, bu nedenle değerlerden daha büyük bir pay alır. Örneğin, fizikte, 6.67e-11'deki Newton'un yerçekimi sabiti gibi gülünç derecede küçük değerlerle uğraşmak zorunda kalırsınız. İyi bir hassasiyete sahip olmak, 100 ile 101 arasında olduğundan daha kullanışlıdır . Daha fazla bilgi için kayan-nokta- gui.de'yi okuyun .
Michael Borgwardt

1
Ayrıca herhangi bir sayıyı 0,0 ile 1,0 arasında ölçeklendirebilir, ölçeği ayrı ayrı takip ederek hesaplamada daha az hata elde edebilirsiniz. Sayı doğrusunun tamamının iki sayı arasında eşleştirilebilmesi çok güzel!
codekaizen

44

Her doubleolan temsili değeri arasındadır 0x0000000000000000ve 0x3ff0000000000000aralık [0.0, 1.0] yatmaktadır. Bu (2 ^ 62 - 2 ^ 52) farklı değerlerdir (uç noktaları sayıp saymamanıza bağlı olarak artı veya eksi bir çift).

[1.0, 2.0] aralığı, 0x3ff0000000000000ve arasındaki temsillere karşılık gelir 0x400000000000000; bu 2 ^ 52 farklı değerdir.

[100.0, 101.0] aralığı, 0x4059000000000000ve arasındaki temsillere karşılık gelir 0x4059400000000000; bu 2 ^ 46 farklı değerdir.

10 ^ 100 ile 10 ^ 100 + 1 arasında çift yoktur . Bu sayılardan hiçbiri çift kesinlikte gösterilemez ve aralarında kalan çiftler yoktur. En yakın iki çift duyarlıklı sayı:

99999999999999982163600188718701095...

ve

10000000000000000159028911097599180...

İyi desteklenen kesin bir cevap için +1. (Eğer son noktalarını sayma üzereyiz seçici, 0,0 ve -0,0 farklı gösterime sahiptir unutmayın.)
Jim Lewis

1
+1, böyle bir bükülme sonu! Bir M. Night Shyamalan senaryosu okuyormuşum gibi hissettim!
poligenel yağlayıcılar

7

Diğerleri, [0.0, 1.0] aralığında yaklaşık 2 ^ 62 çift olduğunu zaten açıklamışlardır.
(Gerçekten şaşırtıcı değil: Neredeyse 2 ^ 64 ayrı sonlu çiftler vardır; olanların, yarım olumludur ve kabaca yarısı bu 1.0 <bulunmaktadır.)

Ama rasgele sayı üreteçleri söz: Bir rasgele sayı üreteci 0.0 ile 1.0 arasındaki sayılar üreten O notu olamaz genel üretmek tüm bu rakamlar; tipik olarak sadece n bir tamsayı ile n / 2 ^ 53 biçiminde sayılar üretir (örneğin nextDouble için Java belgelerine bakın ). Bu nedenle, çıktı için genellikle yalnızca yaklaşık 2 ^ 53 (+/- 1, hangi uç noktaların dahil edildiğine bağlı olarak) olası değerleri vardır random(). Bu, [0.0, 1.0] 'daki çoğu ikiye katlamanın hiçbir zaman oluşturulmayacağı anlamına gelir.


3

Java'nın yeni matematiği, Bölüm 2: IBM'in Kayan noktalı sayılar makalesi , bunu çözmek için aşağıdaki kod parçacığını sunar ( kayan sayılarda , ancak bunun iki katına da çalıştığından şüpheleniyorum):

public class FloatCounter {

    public static void main(String[] args) {
        float x = 1.0F;
        int numFloats = 0;
        while (x <= 2.0) {
            numFloats++;
            System.out.println(x);
            x = Math.nextUp(x);
        }
        System.out.println(numFloats);
    }
}

Bununla ilgili şu yorumu yapıyorlar:

1.0 ve 2.0 arasında tam olarak 8.388.609 dalgalanma olduğu ortaya çıktı; bu aralıkta var olan gerçek sayıların büyük ama sayılamaz sonsuzluğu. Ardışık sayılar yaklaşık 0.0000001 aralıklıdır. Bu mesafeye, en son sırada en az hassaslık veya birim için ULP denir.


Evet, ama bunun için en float, değil double - floatler yüzden, fraksiyonun 23 bits' yetmeyecek kadar 2**23 -> 8388608iki komşu güçler arasında farklı değerler (ders 'kapsayıcı' bir parçası, daha fazla ikisinin sonraki gücünü birini saymak zorunda ortalama). doubles 52 bitlik kesirlere sahiptir!
Alex Martelli

1
@Alex: Sonuçları alabilmem için programı (çiftler için değiştirilmiş) evrenin sonuna kadar çalıştırmam gerekecek sanırım ... :(
Mark Rushakoff

1
Aptal hissediyorum; Ben sadece doubleeşdeğerini yazdım ve "Hey, kendi sorumu yaklaşık 5 dakika içinde cevaplayacağım ..." diye düşündüm
poligenelubricants

1
@polygene: bariz bir yaklaşım ... hesaplamak için olanaksız olduğunu, ancak keyfi bir durum için çözmek için bazı zekice basit bir formül yok olması gereken bir proje Euler sorun gibi bu hissediyor
Mark Rushakoff

2
belki gerçekten kompresörlü süper bilgisayar ile değil: bir makine, iç döngü çalıştırmak için sadece bir nanosaniye alarak sayma üzerine doubleiki komşu güçler arasında 52 gündür hakkında alacaktı ( printlntabii olacağını çok çok hızlı, her ne olursa olsun o aday olma olasılığı Bir cümlenin kaybolduğunu varsayalım ;-). Güçlü ama gerçekçi bir makinede bir yıl veya daha az sürmenin mümkün olduğunu düşünüyorum ;-).
Alex Martelli 05

2
  1. 2 ^ 53 - gizli bit dahil olmak üzere 64 bitlik kayan noktalı sayının anlamlılık / mantisinin boyutu.
  2. Kabaca evet, sifnificand sabit olduğundan, ancak üs değiştiğinden.

Daha fazla bilgi için wikipedia makalesine bakın .


2 için cevabınız FP'nin işleyişini nasıl anladığımla çelişiyor.
poligenel yağlayıcılar

Bence 1gizli bit her zaman biridir çünkü yanlış - bu nedenle 2^52, değil 2^53 farklı değerleri (bitişik iki üssü dahil bir ve dışlanan sonraki arasında - değil ! 0.0 ile 1.0 arasında).
Alex Martelli

1

Java ikilisi bir IEEE 754 ikili64 numarasıdır.

Bu, dikkate almamız gerektiği anlamına gelir:

  1. Mantissa 52 bittir
  2. Üs, 1023 sapmalı 11 bitlik sayıdır (yani, ona 1023 eklenmiş)
  3. Üsün tamamı 0 ise ve mantis sıfır değilse, sayının normalleştirilmemiş olduğu söylenir

Bu temelde, standarda göre 0 ile 1 arasında olan olası ikili temsillerin toplam 2 ^ 62-2 ^ 52 + 1 olduğu anlamına gelir. 2 ^ 52 + 1'in normalize edilmemiş durumları kaldırmak için olduğuna dikkat edin. sayılar.

Mantis pozitifse ancak üs negatifse, sayı pozitif ancak 1'den küçükse :-)

Diğer sayılar için biraz daha zordur çünkü kenar tam sayıları IEEE 754 gösteriminde tam olarak gösterilemeyebilir ve üstte sayıları temsil edebilmek için kullanılan başka bitler olduğundan, sayı ne kadar büyükse o kadar düşük farklı değerler.

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.