主要介紹了Java獲取隨機數的3種方法,主要利用random()函數來實現
方法1
(數據類型)(最小值+Math.random()*(最大值-最小值+1))例:
1
|
( int )( 1 +Math.random()*( 10 - 1 + 1 )) |
從1到10的int型隨數
方法2
獲得隨機數
1
2
3
|
for ( int i= 0 ;i< 30 ;i++) {System.out.println(( int )( 1 +Math.random()* 10 ));} ( int )( 1 +Math.random()* 10 ) |
通過java.Math包的random方法得到1-10的int隨機數
公式是:最小值---最大值(整數)的隨機數
(類型)最小值+Math.random()*最大值
方法3
1
2
3
|
Random ra = new Random(); for ( int i= 0 ;i< 30 ;i++) {System.out.println(ra.nextInt( 10 )+ 1 );} |
通過java.util包中的Random類的nextInt方法來得到1-10的int隨機數
生成0到1之間的任意隨機小數:
生成[0,d)區間的隨機小數,d為任意正的小數,則只需要將nextDouble方法的返回值乘以d即可。
[n1,n2]
也就是 ra.nextDouble() * (n2-n1)+n1
java產生隨機數的幾種方式
一.在j2se里我們可以使用Math.random()方法來產生一個隨機數,這個產生的隨機數是0-1之間的一個double,我們可以把他乘以一定的數,比如說乘以100,他就是個100以內的隨機,這個在j2me中沒有。
二.在java.util這個包里面提供了一個Random的類,我們可以新建一個Random的對象來產生隨機數,他可以產生隨機整數、隨機float、隨機double,隨機long,這個也是我們在j2me的程序里經常用的一個取隨機數的方法。
三.在我們的System類中有一個currentTimeMillis()方法,這個方法返回一個從1970年1月1號0點0分0秒到目前的一個毫秒數,返回類型是long,我們可以拿他作為一個隨機數,我們可以拿他對一些數取模,就可以把他限制在一個范圍之內啦
其實在Random的默認構造方法里也是使用上面第三種方法進行隨機數的產生的
對于方法二中的Random類有以下說明:
java.util.Random類有兩種方式構建方式:帶種子和不帶種子
不帶種子:
此種方式將會返回隨機的數字,每次運行結果不一樣
1
2
3
4
5
6
7
|
public class RandomTest { public static void main(String[] args) { java.util.Random r= new java.util.Random(); for ( int i= 0 ;i< 10 ;i++){ System.out.println(r.nextInt()); } } |
帶種子:
此種方式,無論程序運行多少次,返回結果都是一樣的
1
2
3
4
5
6
|
public static void main(String[] args) { java.util.Random r= new java.util.Random( 10 ); for ( int i= 0 ;i< 10 ;i++){ System.out.println(r.nextInt()); } } |
兩種方式的差別在于
(1) 首先請打開Java Doc,我們會看到Random類的說明:
此類的實例用于生成偽隨機數流,此類使用48 位的種子,該種子可以使用線性同余公式對其進行修改。
如果用相同的種子創建兩個 Random 實例,則對每個實例進行相同的方法調用序列,它們將生成并返回相同的數字序列。為了保證實現這種特性,我們為類Random指定了特定的算法。為了 Java 代碼的完全可移植性,Java 實現必須讓類 Random 使用此處所示的所有算法。但是允許 Random 類的子類使用其他算法,只要其符合所有方法的常規協定即可。
Java Doc對Random類已經解釋得非常明白,我們的測試也驗證了這一點。
(2) 如果沒有提供種子數,Random實例的種子數將是當前時間的毫秒數,可以通過System.currentTimeMillis()來獲得當前時間的毫秒數。打開JDK的源代碼,我們可以非常明確地看到這一點。
1
|
public Random() { this (System.currentTimeMillis()); } |
另外:
random對象的nextInt(),nextInt(int n)方法的說明:
int nextInt() //返回下一個偽隨機數,它是此隨機數生成器的序列中均勻分布的 int 值。
int nextInt(int n) //返回一個偽隨機數,它是從此隨機數生成器的序列中取出的、在 0(包括)和指定值(不包括)之間均勻分布的 int值。
Java隨機數總結
隨機數在實際中使用很廣泛,比如要隨即生成一個固定長度的字符串、數字。或者隨即生成一個不定長度的數字、或者進行一個模擬的隨機選擇等等。Java提供了最基本的工具,可以幫助開發者來實現這一切。
一、Java隨機數的產生方式
在Java中,隨機數的概念從廣義上將,有三種。
1、通過System.currentTimeMillis()來獲取一個當前時間毫秒數的long型數字。
2、通過Math.random()返回一個0到1之間的double值。
3、通過Random類來產生一個隨機數,這個是專業的Random工具類,功能強大。
二、Random類API說明
1、Java API說明
Random類的實例用于生成偽隨機數流。此類使用 48 位的種子,使用線性同余公式對其進行修改(請參閱 Donald Knuth 的《The Art of Computer Programming, Volume 2》,第 3.2.1 節)。
如果用相同的種子創建兩個 Random 實例,則對每個實例進行相同的方法調用序列,它們將生成并返回相同的數字序列。為了保證屬性的實現,為類 Random 指定了特定的算法。
很多應用程序會發現 Math 類中的 random 方法更易于使用。
2、方法摘要
Random() //創建一個新的隨機數生成器。
Random(long seed) //使用單個 long 種子創建一個新隨機數生成器: public Random(long seed) { setSeed(seed); } next 方法使用它來保存隨機數生成器的狀態。
protected int next(int bits):生成下一個偽隨機數。
boolean nextBoolean():返回下一個偽隨機數,它是從此隨機數生成器的序列中取出的、均勻分布的 boolean 值。
void nextBytes(byte[] bytes):生成隨機字節并將其置于用戶提供的字節數組中。
double nextDouble():返回下一個偽隨機數,它是從此隨機數生成器的序列中取出的、在 0.0 和 1.0之間均勻分布的 double 值。
float nextFloat():返回下一個偽隨機數,它是從此隨機數生成器的序列中取出的、在 0.0 和 1.0 之間均勻分布的 float 值。
double nextGaussian():返回下一個偽隨機數,它是從此隨機數生成器的序列中取出的、呈高斯(“正常地”)分布的 double 值,其平均值是 0.0,標準偏差是 1.0。
int nextInt():返回下一個偽隨機數,它是此隨機數生成器的序列中均勻分布的 int 值。
int nextInt(int n):返回一個偽隨機數,它是從此隨機數生成器的序列中取出的、在 0(包括)和指定值(不包括)之間均勻分布的 int值。
long nextLong():返回下一個偽隨機數,它是從此隨機數生成器的序列中取出的、均勻分布的 long 值。
void setSeed(long seed):使用單個 long 種子設置此隨機數生成器的種子。
三、Random類使用說明
1、帶種子與不帶種子的區別Random類使用的根本是策略分帶種子和不帶種子的Random的實例。
通俗說,兩者的區別是:帶種子的,每次運行生成的結果都是一樣的。
不帶種子的,每次運行生成的都是隨機的,沒有規律可言。
2、創建不帶種子的Random對象
1
|
Random random = new Random(); |
3、創建不帶種子的Random對象有兩種方法:
1) Random random = new Random(555L);
2) Random random = new Random();random.setSeed(555L);
四、測試
通過一個例子說明上面的用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
import java.util.Random; public class TestRandomNum { public static void main(String[] args) { randomTest(); testNoSeed(); testSeed1(); testSeed2(); } public static void randomTest() { System.out.println( "--------------test()--------------" ); //返回以毫秒為單位的當前時間。 long r1 = System.currentTimeMillis(); //返回帶正號的 double 值,大于或等于 0.0,小于 1.0。 double r2 = Math.random(); //通過Random類來獲取下一個隨機的整數 int r3 = new Random().nextInt(); System.out.println( "r1 = " + r1); System.out.println( "r3 = " + r2); System.out.println( "r2 = " + r3); } public static void testNoSeed() { System.out.println( "--------------testNoSeed()--------------" ); //創建不帶種子的測試Random對象 Random random = new Random(); for ( int i = 0 ; i < 3 ; i++) { System.out.println(random.nextInt()); } } public static void testSeed1() { System.out.println( "--------------testSeed1()--------------" ); //創建帶種子的測試Random對象 Random random = new Random(555L); for ( int i = 0 ; i < 3 ; i++) { System.out.println(random.nextInt()); } } public static void testSeed2() { System.out.println( "--------------testSeed2()--------------" ); //創建帶種子的測試Random對象 Random random = new Random(); random.setSeed(555L); for ( int i = 0 ; i < 3 ; i++) { System.out.println(random.nextInt()); } } } |
運行結果:
--------------test()--------------
r1 = 1227108626582
r3 = 0.5324887850155043
r2 = -368083737
--------------testNoSeed()--------------
809503475
1585541532
-645134204
--------------testSeed1()--------------
-1367481220
292886146
-1462441651
--------------testSeed2()--------------
-1367481220
292886146
-1462441651
Process finished with exit code 0
通過testSeed1()與testSeed2()方法的結果可以看到,兩個打印結果相同,因為他們種子相同,再運行一次,結果還是一樣的,這就是帶種子隨機數的特性。而不帶種子的,每次運行結果都是隨機的。
五、綜合應用
下面通過最近寫的一個隨機數工具類來展示用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
import java.util.Random; public class RandomUtils { public static final String allChar = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ; public static final String letterChar = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ; public static final String numberChar = "0123456789" ; public static String generateString( int length) { StringBuffer sb = new StringBuffer(); Random random = new Random(); for ( int i = 0 ; i < length; i++) { sb.append(allChar.charAt(random.nextInt(allChar.length()))); } return sb.toString(); } public static String generateMixString( int length) { StringBuffer sb = new StringBuffer(); Random random = new Random(); for ( int i = 0 ; i < length; i++) { sb.append(allChar.charAt(random.nextInt(letterChar.length()))); } return sb.toString(); } public static String generateLowerString( int length) { return generateMixString(length).toLowerCase(); } public static String generateUpperString( int length) { return generateMixString(length).toUpperCase(); } public static String generateZeroString( int length) { StringBuffer sb = new StringBuffer(); for ( int i = 0 ; i < length; i++) { sb.append( '0' ); } return sb.toString(); } public static String toFixdLengthString( long num, int fixdlenth) { StringBuffer sb = new StringBuffer(); String strNum = String.valueOf(num); if (fixdlenth - strNum.length() >= 0 ) { sb.append(generateZeroString(fixdlenth - strNum.length())); } else { throw new RuntimeException( "將數字" + num + "轉化為長度為" + fixdlenth + "的字符串發生異常!" ); } sb.append(strNum); return sb.toString(); } public static String toFixdLengthString( int num, int fixdlenth) { StringBuffer sb = new StringBuffer(); String strNum = String.valueOf(num); if (fixdlenth - strNum.length() >= 0 ) { sb.append(generateZeroString(fixdlenth - strNum.length())); } else { throw new RuntimeException( "將數字" + num + "轉化為長度為" + fixdlenth + "的字符串發生異常!" ); } sb.append(strNum); return sb.toString(); } public static void main(String[] args) { System.out.println(generateString( 15 )); System.out.println(generateMixString( 15 )); System.out.println(generateLowerString( 15 )); System.out.println(generateUpperString( 15 )); System.out.println(generateZeroString( 15 )); System.out.println(toFixdLengthString( 123 , 15 )); System.out.println(toFixdLengthString(123L, 15 )); } } |
運行結果:
vWMBPiNbzfGCpHG
23hyraHdJkKPwMv
tigowetbwkm1nde
BPZ1KNEJPHB115N
000000000000000
000000000000123
000000000000123
Process finished with exit code 0
六、總結
1、隨機數很常用,在Java有三種產生方式,以Random隨機數的使用最為復雜。
2、Random類對象有是否帶種子之分,帶種子的只要種子相同,多次運行,生成隨機數的結果總是那樣。
3、帶種子隨機數的帶種子的對象創建方式有兩種,效果一樣。但是帶種子的隨機數用處似乎不大。
4、Random的功能涵蓋了Math.random()的功能。
5、可以通過隨機數去做實現隨機字符串等復雜的隨機數據。
6、不要研究不重復的隨機數,意義不大。
在Java 中我們可以使用java.util.Random類來產生一個隨機數發生器。它有兩種形式的構造函數,分別是Random()和Random(long seed)。Random()使用當前時間即System.currentTimeMillis()作為發生器的種子,Random(long seed)使用指定的seed作為發生器的種子。
隨機數發生器(Random)對象產生以后,通過調用不同的method:nextInt()、nextLong()、nextFloat()、nextDouble()等獲得不同類型隨機數。
1>生成隨機數
1
2
|
Random random = new Random(); Random random = new Random( 100 ); //指定種子數100 |
random調用不同的方法,獲得隨機數。
如果2個Random對象使用相同的種子(比如都是100),并且以相同的順序調用相同的函數,那它們返回值完全相同。如下面代碼中兩個Random對象的輸出完全相同
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import java.util.*; class TestRandom { public static void main(String[] args) { Random random1 = new Random( 100 ); System.out.println(random1.nextInt()); System.out.println(random1.nextFloat()); System.out.println(random1.nextBoolean()); Random random2 = new Random( 100 ); System.out.println(random2.nextInt()); System.out.println(random2.nextFloat()); System.out.println(random2.nextBoolean()); } } |
2>指定范圍內的隨機數
隨機數控制在某個范圍內,使用模數運算符%
1
2
3
4
5
6
7
8
9
|
import java.util.*; class TestRandom { public static void main(String[] args) { Random random = new Random(); for ( int i = 0 ; i < 10 ;i++) { System.out.println(Math.abs(random.nextInt())); } } } |
獲得的隨機數有正有負的,用Math.abs使獲取數據范圍為非負數
3>獲取指定范圍內的不重復隨機數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
import java.util.*; class TestRandom { public static void main(String[] args) { int [] intRet = new int [ 6 ]; int intRd = 0 ; //存放隨機數 int count = 0 ; //記錄生成的隨機數個數 int flag = 0 ; //是否已經生成過標志 while (count< 6 ){ Random rdm = new Random(System.currentTimeMillis()); intRd = Math.abs(rdm.nextInt()) 2 + 1 ; for ( int i= 0 ;i<count;i++){ if (intRet[i]==intRd){ flag = 1 ; break ; } else { flag = 0 ; } } if (flag== 0 ){ intRet[count] = intRd; count++; } } for ( int t= 0 ;t< 6 ;t++){ System.out.println(t+ "->" +intRet[t]); } } } |
Java中的隨機數是否可以重復?Java中產生的隨機數能否可以用來產生數據庫主鍵?帶著這個問題,我們做了一系列測試。
1.測試一: 使用不帶參數的Random()構造函數
1
2
3
4
5
6
7
8
9
|
public class RandomTest { public static void main(String[] args) { java.util.Random r= new java.util.Random(); for ( int i= 0 ;i< 10 ;i++){ System.out.println(r.nextInt()); } } } |
程序運行結果:
-1761145445
-1070533012
216216989
-910884656
-1408725314
-1091802870
1681403823
-1099867456
347034376
-1277853157
再次運行該程序:
-169416241
220377062
-1140589550
-1364404766
-1088116756
2134626361
-546049728
1132916742
-1522319721
1787867608
從上面的測試我們可以看出,使用不帶參數的Random()構造函數產生的隨機數不會重復。那么,什么情況下Java會產生重復的隨機數呢?且看下面的測試。
2. 測試二:為Random設置種子數
1
2
3
4
5
6
7
8
9
|
public class RandomTest_Repeat { public static void main(String[] args) { java.util.Random r= new java.util.Random( 10 ); for ( int i= 0 ;i< 10 ;i++){ System.out.println(r.nextInt()); } } } |
無論程序運行多少次,其結果總是:
-1157793070
1913984760
1107254586
1773446580
254270492
-1408064384
1048475594
1581279777
-778209333
1532292428
甚至在不同的機器上測試,測試結果也不會改變!
3.原因分析:
(1) 首先請打開Java Doc,我們會看到Random類的說明:
此類的實例用于生成偽隨機數流,此類使用 48 位的種子,該種子可以使用線性同余公式對其進行修改(請參閱 Donald Knuth 的《The Art of Computer Programming, Volume 2》,第 3.2.1 節)。
如果用相同的種子創建兩個 Random 實例,則對每個實例進行相同的方法調用序列,它們將生成并返回相同的數字序列。為了保證實現這種特性,我們為類Random指定了特定的算法。為了 Java 代碼的完全可移植性,Java 實現必須讓類 Random 使用此處所示的所有算法。但是允許 Random 類的子類使用其他算法,只要其符合所有方法的常規協定即可。
Java Doc對Random類已經解釋得非常明白,我們的測試也驗證了這一點。
(2) 如果沒有提供種子數,Random實例的種子數將是當前時間的毫秒數,可以通過System.currentTimeMillis()來獲得當前時間的毫秒數。打開JDK的源代碼,我們可以非常明確地看到這一點。
1
|
public Random() { this (System.currentTimeMillis()); } |
4. 結論:
通過上面的測試和分析,我們會對Random類有較為深刻的理解。同時,我覺得,通過閱讀Java Doc的API文檔,可以很好地提高我們的Java編程能力,做到“知其然”;一旦遇到費解的問題,不妨打開Java的源代碼,這樣我們就能做到“知其所以然”。
java中一般有兩種隨機數,一個是Math中random()方法,一個是Random類。
一、Math.random()
隨即生成0<x<1的小數。
實例:如何寫,生成隨機生成出0~100中的其中一個數呢?
Math.random()返回的只是從0到1之間的小數,如果要50到100,就先放大50倍,即0到50之間,這里還是小數,如果要整數,就強制轉換int,然后再加上50即為50~100.
最終代碼:(int)(Math.random()*50) + 50
二、Random類
1
2
|
Random random = new Random(); //默認構造方法 Random random = new Random( 1000 ); //指定種子數字 |
在進行隨機時,隨機算法的起源數字稱為種子數(seed),在種子數的基礎上進行一定的變換,從而產生需要的隨機數字。
相同種子數的Random對象,相同次數生成的隨機數字是完全相同的。也就是說,兩個種子數相同的Random對象,第一次生成的隨機數字完全相同,第二次生成的隨機數字也完全相同。
2 、Random類中的常用方法
Random 類中的方法比較簡單,每個方法的功能也很容易理解。需要說明的是,Random類中各方法生成的隨機數字都是均勻分布的,也就是說區間內部的數字生成的幾率是均等的。下面對這些方法做一下基本的介紹:
a 、public boolean nextBoolean()
該方法的作用是生成一個隨機的boolean值,生成true和false的值幾率相等,也就是都是50%的幾率。
b 、public double nextDouble()
該方法的作用是生成一個隨機的double值,數值介于[0,1.0)之間,這里中括號代表包含區間端點,小括號代表不包含區間端點,也就是0到1之間的隨機小數,包含0而不包含1.0。
c 、public int nextInt()
該方法的作用是生成一個隨機的int值,該值介于int的區間,也就是-2的31次方到2的31次方-1之間。
如果需要生成指定區間的int值,則需要進行一定的數學變換,具體可以參看下面的使用示例中的代碼。
d 、public int nextInt(int n)
該方法的作用是生成一個隨機的int值,該值介于[0,n)的區間,也就是0到n之間的隨機int值,包含0而不包含n。
如果想生成指定區間的int值,也需要進行一定的數學變換,具體可以參看下面的使用示例中的代碼。
e 、public void setSeed(long seed)
該方法的作用是重新設置Random對象中的種子數。設置完種子數以后的Random對象和相同種子數使用new關鍵字創建出的Random對象相同。
3 、Random類使用示例
使用Random類,一般是生成指定區間的隨機數字,下面就一一介紹如何生成對應區間的隨機數字。以下生成隨機數的代碼均使用以下Random對象r進行生成:
1
|
Random r = new Random(); |
a 、生成[0,1.0)區間的小數
1
|
double d1 = r.nextDouble(); |
直接使用nextDouble方法獲得。
b、生成[0,5.0)區間的小數
1
|
double d2 = r.nextDouble() * 5 ; |
因為nextDouble方法生成的數字區間是[0,1.0),將該區間擴大5倍即是要求的區間。
同理,生成[0,d)區間的隨機小數,d為任意正的小數,則只需要將nextDouble方法的返回值乘以d即可。
c、生成[1,2.5)區間的小數 [n1,n2]
double d3 = r.nextDouble() * 1.5 + 1;【也就是 r.nextDouble() * (n2-n1)+n1】
生成[1,2.5)區間的隨機小數,則只需要首先生成[0,1.5)區間的隨機數字,然后將生成的隨機數區間加1即可。
同理,生成任意非從0開始的小數區間[d1,d2)范圍的隨機數字(其中d1不等于0),則只需要首先生成[0,d2-d1)區間的隨機數字,然后將生成的隨機數字區間加上d1即可。
d、生成任意整數
1
|
int n1 = r.nextInt(); |
直接使用nextInt方法即可。
e、生成[0,10)區間的整數
1
2
|
int n2 = r.nextInt( 10 ); n2 = Math.abs(r.nextInt() % 10 ); |
以上兩行代碼均可生成[0,10)區間的整數。
第一種實現使用Random類中的nextInt(int n)方法直接實現。
第二種實現中,首先調用nextInt()方法生成一個任意的int數字,該數字和10取余以后生成的數字區間為(-10,10),因為按照數學上的規定余數的絕對值小于除數,然后再對該區間求絕對值,則得到的區間就是[0,10)了。
同理,生成任意[0,n)區間的隨機整數,都可以使用如下代碼:
1
2
|
int n2 = r.nextInt(n); n2 = Math.abs(r.nextInt() % n); |
f、生成[0,10]區間的整數
1
2
|
int n3 = r.nextInt( 11 ); n3 = Math.abs(r.nextInt() % 11 ); |
相對于整數區間,[0,10]區間和[0,11)區間等價,所以即生成[0,11)區間的整數。
g、生成[-3,15)區間的整數
1
2
|
int n4 = r.nextInt( 18 ) - 3 ; //【也就是 r.nextInt() * (n2-n1)+n1】 n1是個負數 n4 = Math.abs(r.nextInt() % 18 ) - 3 ; |
生成非從0開始區間的隨機整數,可以參看上面非從0開始的小數區間實現原理的說明。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。