2013-07-07 114 views
2

這可能比編程更多的數學問題。在JS我想,在一個時間間隔返回一個隨機整數讓說1-6的功能,這是我發現:JavaScript隨機數

// Returns a random integer between min and max 
// Using Math.round() will give you a non-uniform distribution! 
function getRandomInt(min, max) { 
    return Math.floor(Math.random() * (max - min + 1)) + min; 
} 

我感到內疚,如果我複製並粘貼在我的代碼。我不明白這一點: 爲什麼我們從max中減去min,加1,然後用Math.random()乘以答案,然後加上min。我在紙上手動累積了幾個數字,它工作得很好!但我不明白爲什麼!

+0

+1僅存在,因爲'max'包含e,不是唯一的。 – Bergi

+0

查看[在特定範圍內的Javascript中生成隨機數?](http://stackoverflow.com/questions/1527803/generating-random-numbers-in-javascript-in-a-specific-range)一個很好的解釋 – Bergi

回答

3

Math.random()會給你一個從0到1的「實數」(不包括1.0)。

這很酷,但如果我想從1到2的「真實」數字呢?

答案:將您的[0,1)「轉換」爲[1,2]。

實際上,這意味着將1加到結果中。

嘗試一下 - Math.random()+1會給你一個號碼從1〜2

在數學這被稱爲「映射」。也就是說,對於[0,1)中的每個可能的實數,找到一種方法將實數「映射」爲[1,2]中的另一個實數。也就是說,如果我給出了[0,1]之間的任何實數,則應該能夠映射該數字 - 將該數字應用於返回[1,2]之間的數字的函數。

在我們的例子中,函數f(x)= x + 1。

你知道這是怎麼給我們之間的[1,2]之間的隨機數?可視化的兩個間隔彼此相鄰和想象[1,2的線在[0,1從每個點要)成其相應的地圖)。現在,在[0,1)...上隨機選擇一個點,然後按照該線。你會按照[1,2]中的隨機點行!

現在,從[0,1)到[1,2]的所有完整的一對一映射會將[0,1)之間的隨機數變成[1,2] ...之間的隨機數。但不是所有人都會給你一個均勻分佈的[1,2]之間的隨機數。背後究竟地圖給你平均分配結果的數學有點複雜,但簡單來說,如果你的地圖只涉及加,減,乘,並通過常量分,這是在這個意義上,結果也將均勻分佈的「法律」。

因此,現在我們知道如何將[0,1)轉換爲[1,2]。

如果我想將[0,1)映射到[0,2)會怎麼樣?我不能只是添加數字了...

如何將所有東西都乘以二?

這應該工作 - 函數f(x)= X * 2 [0,1每一個點),以一個點上確實地圖[0,2)---因爲它只能通過常數涉及乘法(2),它是一個分佈保存圖。

This Works! Math.random()*2會給你一個介於0和2之間的隨機數。

好吧,現在有點複雜了...將[0,1)轉換爲[1,3]。

乘以2不起作用... 0 * 2 = 0,那不在你的目標範圍內。 添加一個不起作用...即使0 + 1在您的目標範圍內,1 + 1也是如此,您無法達到3.

如果我們無法變換[ 0,1)變成[1,3],我們試試看看我們是否可以將其他變換爲[1,3]。

[0,2)如何?是的,我們可以做到這一點...函數f(x)= x + 1完美映射[0,2)到[1,3]。您可以將+視爲「移位」範圍。

所以這裏的解決方案很清楚 - 首先,將[0,1)轉換爲[0,2),然後將[0,2)轉換爲[1,3]。我們已經知道第一個(f(x)= x * 2),並且我們計算出第二個(f(x)= x + 1)。所以「組合」轉換/映射是f(x)=(x * 2)+1。

也就是說,Math.random()*2 + 1會給你一個從0到3

現在的最終招...映射[0,1)到任意的範圍[最小值,最大值)。

這裏的祕訣是將其重寫爲[min,min + range],其中range = max-min。

在這裏您可以看到將範圍[0,範圍]轉換爲[min,min + range]很簡單 - 只需將「min」添加到該範圍即可。所以如果我有範圍[0,範圍],並且我想得到[min,min + range],我會使用f(x)= x + min。

那麼我們如何從[0,1)到[0,範圍]?

乘以範圍!

F(X)=(X *範圍)+分鐘

現在寫事物回原始方面,使用範圍=最大值 - 最小值

F(X)=(X *(最大值 - 最小值))+分

將改變從[0,1實數)從[分鐘的實數,最大值)

我會留下,其餘(把它變成一個有用的整數)給你

+0

非常感謝你給出了很好的答案,我希望自己和數學一樣好。如果有哪種方式可以給我+100000000票! – Adelin

1

這裏是您的代碼的解釋:

  • Math.random()生成(不包括1)在0和1之間的隨機數。
  • 您需要根據您想要的數字範圍來縮放該值。您的範圍是從您的min所需號碼到您的max所需號碼的多少,即max - min
  • 如果您想在生成的數字範圍max值,然後用max - min + 1
  • 然後,您需要確保隨機數開始在正確的基礎,而不是0所以你添加min它。
  • 然後,如果你想要它是一個整數,你可以調用Math.floor()將它截斷爲下一個最小的整數。

所以,如果你只是有這樣的:

Math.floor(Math.random()) 

你會總是爲零。由於0和1(不含1)之間的浮點值Math.floor()總會下來截斷爲0

然後,如果你擴大與範圍:

Math.floor(Math.random() * (max - min + 1)) 

現在你會得到之間的隨機數0和max - min包括較大的值。

所以,然後讓它在正確的基礎開始,您在min添加這樣的:

Math.floor(Math.random() * (max - min + 1)) + min 
5

假設你已經瞭解Math.floorMath.random行爲,這裏的其餘分步:

  • Math.random()↝之間的隨機數0(含)並1(不含)
  • Math.random() * max↝之間0(含)和max(不含)
  • Math.floor(Math.random() * max)↝隨機整數max之間0(包括)和(不包括)的隨機數
  • Math.floor(Math.random() * (max - min)) + minmin(包括之間的隨機整數。 )和max(不含。)
  • Math.floor(Math.random() * ((max + 1) - min)) + min↝隨機min(含)和max+1(不含之間ORminmax兩端)
1
0 <= Math.random() < 1 => 
0 <= Math.random() * 6 < 6 => 
0 <= Math.floor(Math.random() * 6) <= 5 

之間的整數)。(那你添加 '分',因此它會是這樣的:

min <= Math.floor(Math.random() * 6) <= 5 + min

在你爲例,對分= 1,你將擁有所有數字在1-6。

我希望現在很清楚。