JavaScript'in Math.random'u ne kadar rastgele?


117

6 yıldır web sitemde rastgele sayı üreteci sayfam var. Uzun bir süredir, Google'da "rastgele sayı oluşturucu" için birinci veya ikinci sonuçtu ve tartışma forumları ve bloglarda yüzlerce yarışma ve çizim olmasa bile düzinelerce karar vermek için kullanıldı (biliyorum çünkü web günlükleri ve genellikle bir göz atın).

Bugün, düşündüğüm kadar rastgele olmayabileceğini söylemek için biri bana e-posta gönderdi . Çok büyük rasgele sayılar üretmeyi denedi (örneğin, 1 ile 10000000000000000000 arasında) ve neredeyse her zaman aynı sayıda basamak olduğunu buldu. Aslında, işlevi bir döngüye sardım, böylece binlerce sayı üretebildim ve çok büyük sayılar için, varyasyonun yalnızca 2 büyüklük sırası olduğu kesin.

Neden?

İşte döngü versiyonu, böylece kendiniz deneyebilirsiniz:

http://andrew.hedges.name/experiments/random/randomness.html

Hem Mozilla Developer Network'ten alınan basit bir uygulamayı hem de 1997'de artık var olmayan bir web sayfasından kaydırdığım bazı kodları içerir (Paul Houle'nin "Central Randomizer 1.3"). Her yöntemin nasıl çalıştığını görmek için kaynağı görüntüleyin.

Burada ve başka yerlerde Mersenne Twister hakkında okudum . Benim ilgilendiğim şey, JavaScript'in yerleşik Math.random işlevinin sonuçlarında neden daha fazla varyasyon olmayacağıdır . Teşekkürler!


"sarnath'd" olduğu gibi, yumruk attı, ya da bu durumda cevap
maetl

5
Başlıktaki sorunun cevabını arıyorsanız stackoverflow.com/questions/2344312/…
Andrew B.

Yanıtlar:


182

1 ile 100 arasında sayılar verilmiştir.

  • 9 1 hane var (1-9)
  • 90'ın 2 hanesi var (10-99)
  • 1'in 3 hanesi var (100)

1 ile 1000 arasında sayılar verilmiştir.

  • 9 1 basamaklı
  • 90'ın 2 hanesi var
  • 900'ün 3 hanesi var
  • 1 4 hanelidir

ve bunun gibi.

Dolayısıyla, bazılarını rastgele seçerseniz, seçilen sayıların büyük çoğunluğu aynı sayıda basamağa sahip olacaktır, çünkü olası değerlerin büyük çoğunluğu aynı sayıda basamağa sahiptir.


11
Mükemmel ve eşit anlam rastgelelik Fikrin ... ilgisini çekmekte dağıtılmış

19
@ R.Pate - uzun bir ölçekte eşit olarak dağıtılmadıkça rastgele sayı üretimi pek bir
işe yaramaz

3
Yeniden oku. @David, N rastgele sayı seçmenin sonucunu değil, sınırlar arasında ne tür sayıların olduğunu belirtir. Başlığın yanıltıcı olduğunu kabul ediyorum.
nikc.org

3
Kayıt için, hem bunu hem de @ jwoolard'ın yanıtlarını oyladım. Bunu kabul edilen cevap olarak seçtim çünkü örnekler, sayıların dağılımının neden daha fazla basamaklı sayılara çarpıtıldığını kristal olarak açıklığa kavuşturuyor.
Andrew Hedges

1
@ andrew-hedges oldukça haklı - bu daha açık cevap, ama teşekkürler :)
jwoolard

56

Sonuçlarınız gerçekten bekleniyor. Rastgele sayılar 1 ila 10 ^ n aralığında eşit olarak dağıtılırsa, sayıların yaklaşık 9 / 10'unun n basamaklı olmasını ve diğer 9 / 100'ün n-1 basamaklı olmasını beklersiniz.


8
Kesinlikle. Basamak sayısının dağılımının çarpık olacağı tahmin edilmektedir. Bununla birlikte, basamak sayısının logunun dağılımı tekdüze olmalıdır.
Noldorin

45

Farklı rastgelelik türleri vardır. Math.random size tek tip bir sayı dağılımı verir.

Farklı büyüklük sıraları istiyorsanız, güç yasası dağılımı denen şeyi yaratmak için üstel bir fonksiyon kullanmanızı öneririm :

function random_powerlaw(mini, maxi) {
    return Math.ceil(Math.exp(Math.random()*(Math.log(maxi)-Math.log(mini)))*mini)
}

Bu işlev size 2 basamaklı sayılarla ve 3 basamaklı sayılarla aşağı yukarı aynı sayıda 1 basamaklı sayı vermelidir.

Normal dağılım gibi rastgele sayılar için başka dağılımlar da vardır (Gauss dağılımı da denir).


Bu algoritma ile, minimum = 1ve 'yi koydum ve maximum = 10sonuç olarak bazen 11 elde ederim . Muhtemelen Math.flooryerine kullanmak Math.round
Sam Eaton

1
Neden işe yarıyor? Düzgün dağılımı üstel dağılıma dönüştürür mü?
shinzou

@shinzou ben sorulan math.stackexchange ve cevap olarak biraz farklı bir formül var. Kodu, math.stackexchange'den matematiksel olarak türetilmiş formülü yansıtacak şekilde değiştirdim.
Christian

21

Bana tamamen rastgele görünüyor! (İpucu: Tarayıcıya bağlıdır.)

Şahsen, uygulamamın daha iyi olacağını düşünüyorum, ancak HER ZAMAN onaylanması gereken XKCD'den çaldım :

function random() {
  return 4; // Chosen by a fair dice throw. Guaranteed to be random.
}

19
Tarayıcıya bağlı olduğundan bahsedildiği için +1, xkcd'yi bağlamadan ödünç almak için -1.

Gerekli ya da değil, xkcd olduğu için atfediliyor. :)
Arafangion

2
OT: "XKCD" nin bu haftaki bir Üniversite Mücadelesi sorusunun cevabı olmasına şaşırdım ve mutluyum: D
Matt Sach

2
Bergi: Doğrudan bağlantı yeterli değil mi?
Arafangion

Onlar şaka doğru atıf değildi demek düşünüyorum ( "4 = rastgele;" yerine "dönüş 4;")
Eren Tantekin

18

Aşağıdaki makale, math.random () işlevinin başlıca Web tarayıcılarında ne kadar güvenli (değil) olduğunu açıklamaktadır: Amid Klein (2008), "Büyük tarayıcılarda geçici kullanıcı takibi ve Alanlar arası bilgi sızıntısı ve saldırıları" . Tipik Java veya Windows yerleşik PRNG işlevlerinden daha güçlü değildir.

Öte yandan, 2 ^ 19937-1 döneminin SFMT'sinin uygulanması, her bir PRNG dizisi için 2496 bayt dahili durumun korunmasını gerektirir. Bazı insanlar bunu affedilemez bir maliyet olarak görebilir.


1
+1: Bahsedilen makale, orijinal sorunun ne hakkında olduğunun çok ötesinde harika.
Roland Illig

6

10000000000000000000 gibi bir sayı kullanırsanız, Javascript'in kullandığı veri türünün doğruluğunun ötesine geçersiniz. Oluşturulan tüm sayıların "00" ile bittiğini unutmayın.


1
Yine de bu davadaki sorunu bu değil.
Joey

3
@Johannes - bu onun sorunlarından biri :)
annakata

IEE754'ün dağılımı eşit değil. Belki 0 ila 999'u ikilik artışlarla temsil edebilir ve bunun için yeterli hassasiyete sahip olabilirsiniz, böylece birçok kez sayı seçerseniz bu aralıkta eşit bir dağılım olduğunu fark edersiniz. % 10 iki basamaklı ve% 90 üç basamaklı olacaktır. Yine de gerçekten yüksek rakamlara ulaşmaya başladığınızda, artış 1'i aşacaktır. Bir trilyon milyardan bir trilyon milyardan bir trilyon milyardan bine ancak bir trilyon milyardan bir bine geçebilirsiniz. Küçük sayılar / ölçekler için bu etki ihmal edilebilir veya hiç olmayacaktır. Yine de ölçek etkisinin çok daha fazla etkisi olacaktır.
jgmjgm

5

Chaos Game'de JS sözde rasgele sayı üretecini denedim .

Benim Sierpinski üçgeni onun oldukça rasgele diyor ki: Fraktal


2
Üçgen kodunu burada ve jsfiddle / jsbin'i paylaşarak farklı tarayıcılar için pratikte kolayca kontrol edebilir miyiz?
Fabrício Matté

1
Tamam, ama bana birkaç gün verin, çünkü kodu İngilizceye çevirmem gerekiyor. Şimdi Lehçe-ingilizce ve benim çok işim var.
zie1ony

1
@ zie1ony birkaç gün doldu.
trusktr

1
usp :( iş, iş, iş Bağlantı: kubaplas.vot.pl/green/fractal İlk parametre tepe noktası nr'dir . İkincisi, çizgi parçasının kesişme noktasıdır (0'dan 1'e). Sadece deneyin.
zie1ony

4
Link öldü - bunun yerine bir Github deposu olabilir mi?
Mark K Cowan

3

Mesela 1e6'ya kadar sayılar üretiyorsanız, umarım yaklaşık olarak eşit olasılıkla tüm sayıları alırsınız. Bu aynı zamanda, bir rakamdan daha az olan bir sayı alma şansınızın onda bir olduğu anlamına gelir. Yüzde bir, iki basamak daha az elde etme şansı, vb. Başka bir RNG kullanırken çok fazla fark göreceğinizden şüpheliyim, çünkü sayılar arasında logaritmaları değil, tek tip bir dağılımınız var.


0

1'den N'ye eşit olarak dağıtılan rastgele olmayan sayılar aynı özelliğe sahiptir. (Bir anlamda) bunun bir hassasiyet meselesi olduğuna dikkat edin. 0-99 arasındaki tekdüze bir dağılım (tamsayılar olarak), sayılarının% 90'ında iki basamaklıdır. 0-999999 arasındaki tekdüze bir dağılım, beş basamaklı 905 numarasına sahiptir.

Herhangi bir sayı kümesinin (bazıları çok kısıtlayıcı olmayan koşullar altında) bir yoğunluğu vardır. Birisi "rastgele" sayıları tartışmak istediğinde, bu sayıların yoğunluğu belirtilmelidir (yukarıda belirtildiği gibi). Ortak yoğunluk, tekdüze yoğunluktur. Başkaları da var: üstel yoğunluk, normal yoğunluk, vb. Bir rasgele sayı üreteci önermeden önce hangi yoğunluğun ilgili olduğu seçilmelidir. Ayrıca, bir yoğunluktan gelen sayılar, çoğu zaman çaresiz yollarla kolaylıkla başka bir yoğunluğa dönüştürülebilir.

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.