C#安全隨機數生成算法和安全性分析

        如何評價一個隨機數算法?我的認爲,一個好的隨機數算法,能提供足夠的安全性和公平性,並擁有優異的性能。java

        真隨機數發生器因爲價格昂貴,並無獲得廣泛採用。那麼,僞隨機數就出來了,好比sha1prng。僞隨機數的安全性依賴於種子。怎麼實現sha1prng和其餘的僞隨機數算法,咱們如今不作討論。java和C#都有相應的API,java的SecureRandom和C#的RNGCryptoServiceProvider。咱們就不重複再輪子了。算法

        上面的兩個類均可覺得咱們提供僞隨機的字節流。同時java還提供產生安全隨機整數的API了,這裏就不討論java的安全隨機數了。下面說說,怎麼利用僞隨機的字節流產生安全的高強度的隨機整數。數組

        有網友是這樣實現,暫且命名爲FastNextInt。安全

public int FastNextInt(int max)
        {
            byte[] bs = new byte[4];
            generator.GetBytes(bs);
            int value = BitConverter.ToInt32(bs, 0);
            value = value % max;
            if (value < 0) value = -value;
            return value;
        }

這種算法能夠快速地獲得一個「隨機」整數,可是這種方法使得在[0,max)範圍內,各整數出現的頻率是不同的。很明顯,前面k=0x100000000/max*max個整數,先使得0~(max-1)中的整數各出現了0x100000000/max次。而後0~(0x100000000-k)再會出現一次。因此容易計算得,第(0x100000000-k+1)~max-1個數出現的機率爲0x100000000/max/0x100000000=1/max;前面第0~(0x100000000-k)個數出現的機率爲(0x100000000/max+1)/0x10000000。其機率比1/max大了1/0x10000000.所以,出現次數多的數就比出現次數少的數多出了約(1/0x100000000)/(1/max)=max/0x100000000的可能。好比,假設max=0x7FFFFFFF;2,3,4....出現了兩次,其餘數只出現了3次。就相對多出了1/2的可能。舉個例子,若是面向21億觀衆抽獎,明顯這樣就顯得不公平了。dom

        是否是這樣就無解了?首先回過頭思考一下,多出來的可能等於max/0x100000000。若是把分母擴大會怎麼樣?假如將分母擴大到0x10000000000000000,max在32位的範圍內,多出來的可能約爲幾十億分之一,是否是能夠忽略不計?因而就有了FastNextLongide

public long FastNextLong(long max)
        {
            byte[] bs = new byte[8];
            generator.GetBytes(bs);
            long value = BitConverter.ToInt64(bs, 0);
            value = value % max;
            if (value < 0) value = -value;
            return value;
        }

        這樣,既保持了良好的運算性能,又得到更公平的隨機數。性能

        有沒有更加公平、安全的隨機數算法。答案是有的,而且是符合數學理論的。因爲咱們的計算機式二進制的,因此只能產生1,2,3,……位的隨機數,也就是說能夠產生0~1,0~3,0~7,0~15,……這種範圍隨機數。每一個數出現的可能只能是1/(2^1),1/(2^2) ,……其實,咱們能夠這樣作,若是咱們要產生0~n的隨機數,咱們先求出K,其中K是知足n<=2^k的k的最小整數值。接着產生一個K位的隨機序列。若是這個序列表示的值屬於0~n,那麼輸出這個數值。在得到輸出的條件下,容易獲得0~n出現的可能性都是相等的。若是這個序列表示的值大於n,那麼再產生一個新數列,循環操做,直到這個序列知足輸出條件。容易獲得,一個序列得到輸出的可能性大於1/2.繼續下一輪循環的可能性小於1/2.根據數學的N次獨立重複試驗機率計算公式,N次沒有得到輸出的可能性小於(1/2)^N。例如,操做10輪後,沒有得到輸出的可能性爲1/1024.又因爲這個機率是指數級減少的,同時,只用到了移位,比較就能夠實現。因此這個算法並不須要多少計算資源就能夠得到輸出。因爲FastNextInt用到了耗時的模除,因此這個算法並不比FastNextInt更耗多少資源。測試

        下面是完整的源代碼。ui

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace RNG
{
    public class SecureRandom
    {
        private readonly static double DOUBLE_UNIT = 1.0 / (1L << 53);
        RandomNumberGenerator generator;
        public SecureRandom(RandomNumberGenerator generator)
        {
            this.generator = generator;
        }
        //產生bits位的隨機整數
        // bits>=1
        protected uint Next(int bits)
        {
            byte[] bs = new byte[4];
            generator.GetBytes(bs);
            uint x = BitConverter.ToUInt32(bs, 0);
            return x >> (32 - bits);
        }
        //產生bits位的隨機整數
        //bits>=1
        protected ulong Next2(int bits)
        {
            byte[] bs = new byte[8];
            generator.GetBytes(bs);
            ulong x = BitConverter.ToUInt64(bs, 0);
            return x >> (64 - bits);
        }


        protected int BitLength(int x)
        {
            int len = 0;
            while (x > 0)
            {
                len++;
                x >>= 1;
            }
            return len;
        }
        protected int BitLength(long x)
        {
            int len = 0;
            while (x > 0)
            {
                len++;
                x >>= 1;
            }
            return len;
        }

        public int NextInt()
        {
            return (int)Next(32);
        }
        //max>=1,不包括max
        public int NextInt(int max)
        {
            if (max <= 0) throw new ArgumentException("max <= 0");
            int len = BitLength(max);
            uint x = Next(len);
            while (x >= max)
            {
                x = Next(len);
            }
            return (int)x;
        }
        //不包括max
        public int NextInt(int min, int max)
        {
            return NextInt(max - min) + min;
        }
        //max>=1,不包括max
        public int FastNextInt(int max)
        {
            byte[] bs = new byte[4];
            generator.GetBytes(bs);
            int value = BitConverter.ToInt32(bs, 0);
            value = value % max;
            if (value < 0) value = -value;
            return value;
        }
        //不包括max
        public int FastNextIntint(int min, int max)
        {
            return FastNextInt(max - min) + min;
        }
        public long NextLong()
        {
            return ((long)(Next(32)) << 32) + Next(32);
        }
        //max>=1,不包括max
        public long NextLong(long max)
        {
            if (max <= 0) throw new ArgumentException("max <= 0");
            int len = BitLength(max);
            ulong x = Next2(len);
            while (x >= (ulong)max)
            {
                x = Next2(len);
            }
            return (long)x;
        }
        //不包括max
        public long NextLong(long min, long max)
        {
            return NextLong(max - min) + min;
        }
        //max>=1,不包括max
        public long FastNextLong(long max)
        {
            byte[] bs = new byte[8];
            generator.GetBytes(bs);
            long value = BitConverter.ToInt64(bs, 0);
            value = value % max;
            if (value < 0) value = -value;
            return value;
        }
        //不包括max
        public long FastNextLong(long min, long max)
        {
            return FastNextLong(max - min) + min;
        }
        public bool NextBoolean()
        {
            return Next(1) != 0;
        }
        //此方法是java源碼中拷貝,此算法獲得的浮點數的隨機性未考究
        public float NextFloat()
        {
            return Next(24) / ((float)(1 << 24));
        }
        //此方法是java源碼中拷貝,此算法獲得的浮點數的隨機性未考究
        public double NextDouble()
        {
            return (((long)(Next(26)) << 27) + Next(27)) * DOUBLE_UNIT;
        }

        //數組長度須要一致
        protected bool GreaterThanOrEqual(byte[] a, byte[] b)
        {
            //if (a.Length > b.Length) return true;
            //if (a.Length < b.Length) return false;
            for (int i = 0; i < a.Length; i++)
            {
                if (a[i] > b[i]) return true;
                if (a[i] < b[i]) return false;
            }
            return true;//全等
        }

        protected byte[] Next3(int bits)
        {
            int len = (bits + 7) >> 3;
            byte[] bs = new byte[len];
            generator.GetBytes(bs);
            bs[0] >>= (8 - bits) & 0x7;
            return bs;
        }
        protected int BitLength(byte[] x)
        {
            int i = 0;
            for (; i < x.Length && x[i] == 0; i++) ;
            return i == 8 ? 0 : BitLength(x[i]) + (x.Length - i - 1) * 8;
        }

        public byte[] NextBigInt(byte[] max)
        {
            int bitLen = BitLength(max);
            if(bitLen==0) throw new ArgumentException("max == 0");
            byte[] max_ = new byte[(bitLen + 7) >>3];
            Array.Copy(max, max.Length - max_.Length, max_, 0, max_.Length);
            byte[] x = Next3(bitLen);
            while (GreaterThanOrEqual(x,max_))
            {
                x = Next3(bitLen);
            }
            return x;
        }
    }
}

測試用的源代碼this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace RNG
{
    class Program
    {
        private static void testRandomInt()
        {
            RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
            SecureRandom random = new SecureRandom(rngCsp);
            Console.WriteLine("===========testRandomInt============");
            int max = 300;
            int[] counter = new int[max];
            int total = 10000000;
            for (int i = 1; i < total; i++)
            {
                counter[random.NextInt(max)]++;
            }
            foreach (int x in counter)
            {
                double diff = (x * max - total) * 100.0 / total;
                Console.WriteLine(string.Format("{0,10}\t{1}%", x, diff));
            }
            Console.WriteLine("=======================");
        }
        private static void testFastRandomInt()
        {
            RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
            SecureRandom random = new SecureRandom(rngCsp);
            Console.WriteLine("===========testFastRandomInt============");
            int max = 300;
            int[] counter = new int[max];
            int total = 10000000;
            for (int i = 1; i < total; i++)
            {
                counter[random.FastNextInt(max)]++;
            }
            foreach (int x in counter)
            {
                double diff = (x * max - total) * 100.0 / total;
                Console.WriteLine(string.Format("{0,10}\t{1}%", x, diff));
            }
            Console.WriteLine("=======================");
        }
        private static void testRandomLong()
        {
            RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
            SecureRandom random = new SecureRandom(rngCsp);

            Console.WriteLine("===========testRandomLong============");
            Console.WriteLine(random.NextLong(123456789012345678));
            Console.WriteLine("=======================");
        }
        private static void testRandomBool()
        {
            RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
            SecureRandom random = new SecureRandom(rngCsp);

            Console.WriteLine("==========testRandomBool=============");
            Console.WriteLine(random.NextBoolean());
            Console.WriteLine("--------------");
            int[] counter = new int[2];
            int total = 10000000;
            for (int i = 1; i < total; i++)
            {
                counter[random.NextBoolean() ? 1 : 0]++;
            }
            foreach (int x in counter)
            {
                double diff = (x * 2 - total) * 100.0 / total;
                Console.WriteLine(string.Format("{0,10}\t{1}%", x, diff));
            }
        }
        public static void Print(byte[] bs)
        {
            foreach (byte b in bs)
            {
                Console.Write(string.Format("{0:x2}", b));
            }
            Console.WriteLine("");
        }

        static void Main(string[] args)
        {
            
            testRandomInt();
            testFastRandomInt();
            testRandomLong();
            testRandomBool();
            
            RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
            SecureRandom random = new SecureRandom(rngCsp);
            Console.WriteLine("random float:" + random.NextFloat());
            Console.WriteLine("random double:" + random.NextDouble());

            Console.WriteLine("==========testRandomBigInt 1=============");
            byte[] max = { 0x00, 0x00,0x11, 0x22, 0x33, 0x44, 0x55};
            for (int i = 0; i < 20; i++)
            {
                byte[] r = random.NextBigInt(max);
                Print(r);
            }
            Console.WriteLine("==========testRandomBigInt 2=============");
            byte[] max2 = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
            for (int i = 0; i < 20; i++)
            {
                byte[] r = random.NextBigInt(max2);
                Print(r);
            }
            Console.Read();
        }
    }
}

輸出:

===========testRandomInt============
     33217	-0.349%
     33458	0.374%
     33367	0.101%
     33418	0.254%
     33479	0.437%
     33358	0.074%
     33332	-0.004%
     33259	-0.223%
     33204	-0.388%
     33287	-0.139%
     33335	0.005%
     33293	-0.121%
     33546	0.638%
     33104	-0.688%
     33673	1.019%
     33551	0.653%
     33394	0.182%
     33132	-0.604%
     33465	0.395%
     33349	0.047%
     33523	0.569%
     33544	0.632%
     33367	0.101%
     33292	-0.124%
     32927	-1.219%
     33178	-0.466%
     33640	0.92%
     33476	0.428%
     33171	-0.487%
     33171	-0.487%
     33077	-0.769%
     33266	-0.202%
     33321	-0.037%
     33594	0.782%
     33561	0.683%
     33226	-0.322%
     33140	-0.58%
     33426	0.278%
     33333	-0.001%
     33448	0.344%
     33411	0.233%
     33356	0.068%
     32972	-1.084%
     33606	0.818%
     33135	-0.595%
     33349	0.047%
     33087	-0.739%
     33231	-0.307%
     33385	0.155%
     33786	1.358%
     33388	0.164%
     33485	0.455%
     32996	-1.012%
     33473	0.419%
     33301	-0.097%
     33078	-0.766%
     33146	-0.562%
     33480	0.44%
     33205	-0.385%
     33440	0.32%
     33335	0.005%
     33264	-0.208%
     33305	-0.085%
     33400	0.2%
     33227	-0.319%
     33078	-0.766%
     33179	-0.463%
     33205	-0.385%
     33422	0.266%
     33156	-0.532%
     33223	-0.331%
     32930	-1.21%
     33474	0.422%
     33241	-0.277%
     33126	-0.622%
     33117	-0.649%
     33194	-0.418%
     33467	0.401%
     33277	-0.169%
     33384	0.152%
     33341	0.023%
     33667	1.001%
     33333	-0.001%
     33139	-0.583%
     33335	0.005%
     33615	0.845%
     33555	0.665%
     33518	0.554%
     33536	0.608%
     33063	-0.811%
     33592	0.776%
     33602	0.806%
     33368	0.104%
     33645	0.935%
     33289	-0.133%
     33401	0.203%
     33494	0.482%
     33247	-0.259%
     33510	0.53%
     33592	0.776%
     33258	-0.226%
     32824	-1.528%
     32927	-1.219%
     33043	-0.871%
     33420	0.26%
     33005	-0.985%
     33554	0.662%
     33627	0.881%
     32940	-1.18%
     33488	0.464%
     33332	-0.004%
     33300	-0.1%
     33448	0.344%
     33493	0.479%
     33489	0.467%
     32892	-1.324%
     33263	-0.211%
     33310	-0.07%
     33166	-0.502%
     33554	0.662%
     33397	0.191%
     33308	-0.076%
     33227	-0.319%
     33335	0.005%
     33403	0.209%
     33337	0.011%
     33099	-0.703%
     33496	0.488%
     33249	-0.253%
     33263	-0.211%
     33387	0.161%
     33399	0.197%
     33414	0.242%
     33303	-0.091%
     33642	0.926%
     33433	0.299%
     33280	-0.16%
     33474	0.422%
     32977	-1.069%
     33694	1.082%
     33363	0.089%
     33199	-0.403%
     33429	0.287%
     33767	1.301%
     33147	-0.559%
     33634	0.902%
     33493	0.479%
     33310	-0.07%
     33134	-0.598%
     33322	-0.034%
     33322	-0.034%
     33037	-0.889%
     33623	0.869%
     33197	-0.409%
     33403	0.209%
     33259	-0.223%
     33208	-0.376%
     33049	-0.853%
     33141	-0.577%
     33457	0.371%
     33381	0.143%
     33011	-0.967%
     33221	-0.337%
     33097	-0.709%
     33179	-0.463%
     33115	-0.655%
     33412	0.236%
     33348	0.044%
     33251	-0.247%
     33438	0.314%
     33209	-0.373%
     33278	-0.166%
     33498	0.494%
     33189	-0.433%
     33328	-0.016%
     33560	0.68%
     33385	0.155%
     33224	-0.328%
     33594	0.782%
     33567	0.701%
     33309	-0.073%
     33314	-0.058%
     33476	0.428%
     33328	-0.016%
     33410	0.23%
     32904	-1.288%
     33314	-0.058%
     33197	-0.409%
     33295	-0.115%
     33345	0.035%
     33471	0.413%
     33354	0.062%
     33323	-0.031%
     33406	0.218%
     33479	0.437%
     33417	0.251%
     33509	0.527%
     33645	0.935%
     33466	0.398%
     33441	0.323%
     33317	-0.049%
     33201	-0.397%
     33135	-0.595%
     33595	0.785%
     33323	-0.031%
     33037	-0.889%
     33579	0.737%
     33160	-0.52%
     33231	-0.307%
     33718	1.154%
     33556	0.668%
     33452	0.356%
     33228	-0.316%
     33232	-0.304%
     33157	-0.529%
     33216	-0.352%
     33464	0.392%
     33397	0.191%
     33217	-0.349%
     33467	0.401%
     33348	0.044%
     33336	0.008%
     33367	0.101%
     33420	0.26%
     33109	-0.673%
     33590	0.77%
     33350	0.05%
     33415	0.245%
     33568	0.704%
     33330	-0.01%
     33415	0.245%
     33178	-0.466%
     33261	-0.217%
     33105	-0.685%
     33268	-0.196%
     33327	-0.019%
     32926	-1.222%
     33311	-0.067%
     33131	-0.607%
     33169	-0.493%
     33375	0.125%
     33435	0.305%
     33060	-0.82%
     33472	0.416%
     33408	0.224%
     33285	-0.145%
     33223	-0.331%
     33417	0.251%
     33169	-0.493%
     33608	0.824%
     33407	0.221%
     33281	-0.157%
     33013	-0.961%
     33494	0.482%
     33717	1.151%
     33266	-0.202%
     33765	1.295%
     33337	0.011%
     33302	-0.094%
     33603	0.809%
     33235	-0.295%
     33670	1.01%
     33575	0.725%
     33336	0.008%
     33358	0.074%
     33018	-0.946%
     33350	0.05%
     33284	-0.148%
     33275	-0.175%
     33494	0.482%
     33523	0.569%
     33345	0.035%
     32958	-1.126%
     33685	1.055%
     33173	-0.481%
     33580	0.74%
     33011	-0.967%
     33201	-0.397%
     33516	0.548%
     33203	-0.391%
     33108	-0.676%
     33422	0.266%
     33332	-0.004%
     33468	0.404%
     33205	-0.385%
     33515	0.545%
     33154	-0.538%
     33366	0.098%
     33577	0.731%
     33368	0.104%
     33381	0.143%
     33279	-0.163%
     33160	-0.52%
     33455	0.365%
     32875	-1.375%
     33365	0.095%
     33417	0.251%
     33287	-0.139%
     33377	0.131%
     33165	-0.505%
=======================
===========testFastRandomInt============
     33538	0.614%
     33470	0.41%
     33167	-0.499%
     33034	-0.898%
     33329	-0.013%
     33281	-0.157%
     33264	-0.208%
     33286	-0.142%
     33156	-0.532%
     33259	-0.223%
     33169	-0.493%
     33066	-0.802%
     33132	-0.604%
     33283	-0.151%
     33316	-0.052%
     33424	0.272%
     33112	-0.664%
     33509	0.527%
     33149	-0.553%
     33213	-0.361%
     33151	-0.547%
     33218	-0.346%
     33195	-0.415%
     33209	-0.373%
     33038	-0.886%
     33107	-0.679%
     33515	0.545%
     33390	0.17%
     33475	0.425%
     33165	-0.505%
     33273	-0.181%
     33484	0.452%
     33283	-0.151%
     33664	0.992%
     33616	0.848%
     33600	0.8%
     33406	0.218%
     33383	0.149%
     33220	-0.34%
     32926	-1.222%
     33187	-0.439%
     33591	0.773%
     33448	0.344%
     33520	0.56%
     33448	0.344%
     33625	0.875%
     33255	-0.235%
     33346	0.038%
     33282	-0.154%
     33403	0.209%
     33381	0.143%
     33652	0.956%
     33075	-0.775%
     33433	0.299%
     33357	0.071%
     33302	-0.094%
     33628	0.884%
     33357	0.071%
     33460	0.38%
     33125	-0.625%
     33703	1.109%
     32828	-1.516%
     33311	-0.067%
     33626	0.878%
     33288	-0.136%
     33006	-0.982%
     33172	-0.484%
     33392	0.176%
     33244	-0.268%
     33347	0.041%
     33537	0.611%
     33386	0.158%
     33232	-0.304%
     33320	-0.04%
     33461	0.383%
     33064	-0.808%
     32988	-1.036%
     33319	-0.043%
     33574	0.722%
     33055	-0.835%
     33238	-0.286%
     33436	0.308%
     33488	0.464%
     33548	0.644%
     33423	0.269%
     33193	-0.421%
     33348	0.044%
     33147	-0.559%
     33380	0.14%
     33113	-0.661%
     33509	0.527%
     33464	0.392%
     33174	-0.478%
     33030	-0.91%
     33081	-0.757%
     33496	0.488%
     33176	-0.472%
     33427	0.281%
     33304	-0.088%
     33082	-0.754%
     33138	-0.586%
     33477	0.431%
     33267	-0.199%
     33516	0.548%
     33420	0.26%
     33099	-0.703%
     33208	-0.376%
     33456	0.368%
     33087	-0.739%
     33502	0.506%
     33255	-0.235%
     33512	0.536%
     33098	-0.706%
     33095	-0.715%
     33330	-0.01%
     33091	-0.727%
     33480	0.44%
     33281	-0.157%
     33529	0.587%
     33127	-0.619%
     33353	0.059%
     33066	-0.802%
     33503	0.509%
     33472	0.416%
     33530	0.59%
     33482	0.446%
     33035	-0.895%
     33374	0.122%
     33494	0.482%
     33309	-0.073%
     33577	0.731%
     33269	-0.193%
     33210	-0.37%
     33867	1.601%
     33728	1.184%
     33459	0.377%
     33500	0.5%
     33522	0.566%
     33602	0.806%
     33284	-0.148%
     33259	-0.223%
     33314	-0.058%
     33368	0.104%
     33579	0.737%
     33619	0.857%
     33150	-0.55%
     33637	0.911%
     33467	0.401%
     33354	0.062%
     33467	0.401%
     33414	0.242%
     33390	0.17%
     33279	-0.163%
     33263	-0.211%
     33473	0.419%
     33596	0.788%
     33208	-0.376%
     33170	-0.49%
     33539	0.617%
     33550	0.65%
     33466	0.398%
     33326	-0.022%
     33350	0.05%
     33285	-0.145%
     33342	0.026%
     33319	-0.043%
     33445	0.335%
     33533	0.599%
     33184	-0.448%
     33501	0.503%
     33288	-0.136%
     33290	-0.13%
     33333	-0.001%
     33624	0.872%
     33045	-0.865%
     33096	-0.712%
     33269	-0.193%
     33145	-0.565%
     33185	-0.445%
     33408	0.224%
     33526	0.578%
     33349	0.047%
     33178	-0.466%
     33502	0.506%
     33510	0.53%
     33372	0.116%
     33062	-0.814%
     33779	1.337%
     33157	-0.529%
     33397	0.191%
     33026	-0.922%
     33282	-0.154%
     33306	-0.082%
     33146	-0.562%
     33090	-0.73%
     33502	0.506%
     33488	0.464%
     33656	0.968%
     33351	0.053%
     33379	0.137%
     33152	-0.544%
     33468	0.404%
     33174	-0.478%
     33055	-0.835%
     33168	-0.496%
     33462	0.386%
     33172	-0.484%
     33327	-0.019%
     33037	-0.889%
     33233	-0.301%
     33697	1.091%
     33328	-0.016%
     33368	0.104%
     33489	0.467%
     33708	1.124%
     33007	-0.979%
     33276	-0.172%
     33443	0.329%
     33374	0.122%
     33187	-0.439%
     33103	-0.691%
     33489	0.467%
     33280	-0.16%
     33409	0.227%
     32945	-1.165%
     33561	0.683%
     33138	-0.586%
     33640	0.92%
     33466	0.398%
     33459	0.377%
     33366	0.098%
     32991	-1.027%
     33207	-0.379%
     33594	0.782%
     33281	-0.157%
     33130	-0.61%
     33314	-0.058%
     33345	0.035%
     33431	0.293%
     33297	-0.109%
     33590	0.77%
     33193	-0.421%
     33304	-0.088%
     33351	0.053%
     33235	-0.295%
     33142	-0.574%
     33263	-0.211%
     33482	0.446%
     33223	-0.331%
     33289	-0.133%
     33338	0.014%
     33507	0.521%
     33394	0.182%
     33453	0.359%
     33246	-0.262%
     33453	0.359%
     33539	0.617%
     33325	-0.025%
     33253	-0.241%
     33337	0.011%
     33165	-0.505%
     33571	0.713%
     33623	0.869%
     33173	-0.481%
     33471	0.413%
     33086	-0.742%
     33369	0.107%
     33115	-0.655%
     33343	0.029%
     33403	0.209%
     32854	-1.438%
     33189	-0.433%
     33300	-0.1%
     33341	0.023%
     33441	0.323%
     33264	-0.208%
     33180	-0.46%
     33357	0.071%
     33385	0.155%
     33345	0.035%
     33421	0.263%
     33367	0.101%
     33401	0.203%
     33406	0.218%
     33115	-0.655%
     33422	0.266%
     33607	0.821%
     33404	0.212%
     33451	0.353%
     33230	-0.31%
     33178	-0.466%
     33461	0.383%
     33324	-0.028%
     33240	-0.28%
     33490	0.47%
     32960	-1.12%
     33372	0.116%
     33466	0.398%
     33318	-0.046%
     33451	0.353%
=======================
===========testRandomLong============
89007644488221403
=======================
==========testRandomBool=============
True
--------------
   4997827	-0.04346%
   5002172	0.04344%
random float:0.7498122
random double:0.58139231767367
==========testRandomBigInt 1=============
06df2c4218
0f47eca524
015f02f9d5
0f1bbf3f04
079e0c47ec
0f11fc561f
111cff258c
00c714f655
0c13b76a76
08cb5865ed
0d24079f32
077954d85f
02fc20247c
042a1ce9e4
0cb20f09e2
01e0c30157
019759a1cc
04916840ae
01bb6903c4
0b06f70539
==========testRandomBigInt 2=============
05c45b4bfdd10e538a46add39d3d7e
0836f2f2ef3a099f3674570188f41c
07d570c291195e756bea83d57b3fdf
0329ed611034ed5a28bb844d879eba
04fafcd289d51cac801cac4b9d8f14
07f420c929e9bfa4ea2629838b1b6a
0793343227d8dccda7703d15c259f2
039a719df657299bd1110b57e14969
099c6c1a7cc2b026a8727fbc7eb66e
09416bc3497afb3bc55b93aa634bd7
032de0780dc126e5a4d5de90198c7b
017a8bc3ea7d0f43c177e90c7c917b
0c90302f216d055a1ece20654ffe70
024af92f2c29ea4a4c63b27d5d3c07
0f312181d44cc16192632e21b914c2
0f3bd1eae26d73d6a7591b8b73784d
0cc25269624d2fbddd7615424015ee
04ce83e8decaa1b6aa58f3615ae999
02be0a29ded1dd3826ede7100aa138
03798b94c2a391b97325d2d647583a

        從中能夠發現,隨機性是獲得保證的。

        建議,在通常使用的時候,max比較小的時候能夠採用FastNextInt或者FastNextLong,最好使用後者,這樣max在32位的範圍內,隨機性公平都能獲得保證,其中將long型結果強制轉換成int便可。固然,追求更高安全,更加公平的能夠選擇NextInt和NextLong。

        再最後還作了一些拓展,實現了NextBigInt,其中參數max是大整數轉化爲大端序的字節數組。例如0x112233可用大端序字節數組表示爲{0x11,0x220,0x33}。在不少使用了大整數的程序中,RSA和ECC加密中都用到了隨機的大整數,基本思路和這裏的同樣。他們是這樣是作的,計算出隨機整數的上限(max),再計算出max的字節數N。而後產生N個字節的隨機字節數組。而後判斷這個字節數組對應的大整數值是否在max之內。這種實現的隨機性(包括在數學理論上)也是能夠獲得保證的,你們能夠參考上面的分析。可是這種實現的效率過低。假如這個max的最高位所在的字節是1,那麼相應的隨機字節序列的這個字節,出現1或0的機率爲2/128.那麼操做10次,還未獲得合適的隨機字節序列的機率爲(63/64)^10≈0.8543。100次未獲得合適的隨機字節序列的機率爲0.2070。而NextBigInt操做3次就能夠獲得這樣的效果(1/8=0.125)。

相關文章
相關標籤/搜索