2012-05-07 330 views
1

在Java中我有一個隨機生成器,生成從-2^63到2^63的隨機數,這不是java.util.Random。從隨機長生成隨機數

我需要生成的(0,1)隨機雙,這是我迄今所做的:

return (seed/(double)(9223372036854775807L))/2+0.5;//seed is a random long 

這是正確的?有沒有數字問題(下溢?)?

可能會更好/更快?

謝謝。

+0

可以擺脫'/ 2'和摺疊說成'種子/ xxx'部分 –

+0

沒有,那將是太偉大了,是一個漫長的。 –

+0

做一個雙 –

回答

1

我會用Math.scalb作爲最有效,並確保有沒有搞笑的行爲,由於四捨五入或表示錯誤

double d = Math.scalb(seed >>> 1, -63); 

只能在雙所以一些將被丟棄使用53位。

如果運行

long seed = Long.MAX_VALUE; 
System.out.println(Math.scalb(seed >>> 1, -63)); 

打印

0.5 

爲0的種子,你得到0.0

隨着-1你得到1.0

+0

用此: double d = Math.scalb(seed >>> 1,63); return d + 0.5; 我得到這些數字: 7.60172909551165E27 | 2.6062896340692396E35 | 4.0765687952289006E36 –

+0

對不起,得到了錯誤的方式。你可以'返回d;' –

+0

惠特這個種子-7545188140698174557 我得到這個數字1.1819490194320679(它大於1)。 –

0

不完全。我認爲更簡單的方法是做到以下幾點: new Random(seed).nextDouble()

+0

我沒有使用Java隨機。 –

+0

@FabioF。但是你沒有說過你不能。 ;) –

1

我寧願只看到一個部門。

0.5+(seed/1.84467440737096E+19); 

這就是說,你要對問題進行浮點精確度,因爲你有64個隨機整數位,然後嘗試擠進雙精度53位跑起來。您可能更適合爲浮點值製作專用的發生器,但我無法確定,因爲我不知道您的動機。

+0

我需要一個很長的時間,通常發生器用於隨機長期,但我也應該實現雙隨機。 –

0

除非我誤讀了需要從0到1的隨機double,否則Java內置的Math.random就是這樣做的。所以你可以避免你目前正在進行的所有轉換。

1

的最快方式種子可能只是將您的前三位設置爲0然後使用那些位,使雙:

double rand = Double.longBitsToDouble(seed & 0x1FFFFFFFFFFFFFFFL); 

這是通過迫使符號爲正,而指數比0少,這將導致尾數是正確的至少一次移動。假設long中的所有整數都是完全隨機的,它會得到均勻的分佈。下面是一個使用隨機生成隨機渴望一個完整的Java程序,則此方法將它們轉換爲0和1之間翻一番的:

import java.util.Random; 

class Main{ 
    public static void main(String[] args){ 
     Random rand = new Random(); 
     long seed = rand.nextLong(); 
     double x = Double.longBitsToDouble(seed & 0x1FFFFFFFFFFFFFFFL); 
     System.out.println(x); 
    } 
} 

這是10個處決輸出:

1.1211565592484309E-247 
8.84224349357039E-242 
6.956043405745214E-271 
3.747746366809532E-232 
9.302628573486166E-158 
1.1440116527034282E-166 
1.2574577719255876E-198 
5.104999671234867E-269 
3.360619724894072E-213 
1.5654452507283312E-220 

編輯

這給了所有可能的雙打0和1之間的均勻分佈,因爲有更多的小雙打,你可能永遠都不會看到接近的條數1.您可以通過生成新的expone解決這個問題NT基於現有一個的位,但你需要一個循環做到這一點,所以它可能不是最快的方法在保理這個後:

long exponent = 0; 
for(int i = 52; (seed >>> i & 1) > 0; i++) exponent++; 
double x = Double.longBitsToDouble(seed & 0x000FFFFFFFFFFFFFL | ((1022 - exponent) << 52)); 

0.4773960377161338
0.929045618651037
0.7183096209363845
0.33962049395497845
0.45568660174922454
0.11670190555677815
0.09371618427480996
0.819287 0898479095
0.9365016017283178
0.11311614413193898

+0

嗡嗡聲,我刪除了評論..現在的數字在範圍內和隨機..但非常接近零..我應該做更多的測試! :) –

+0

@FabioF。嗯,這是均勻隨機分配**所有**可能的兩倍,介於0和1之間,但由於有更多可能的小雙打,它在這個意義上分配不均勻。 – Paulpro

+0

Whao,這是輝煌和可怕的..無論如何,我是大於1(1.3484676232953214,惠特這個長9223048428104072362)。 –