v7.3.2018.0614   重构高性能资源池,减少GC压力,增加线程池,让异步任务得到平等竞争CPU的机会
大石头 编写于 2018-06-14 17:56:44
X
using System;
using System.Security.Cryptography;
using System.Text;
using NewLife.Collections;

namespace NewLife.Security
{
    /// <summary>随机数</summary>
    public static class Rand
    {
        private static RandomNumberGenerator _rnd;

        static Rand()
        {
            _rnd = new RNGCryptoServiceProvider();
        }

        /// <summary>返回一个小于所指定最大值的非负随机数</summary>
        /// <param name="max">返回的随机数的上界(随机数不能取该上界值)</param>
        /// <returns></returns>
        public static Int32 Next(Int32 max = Int32.MaxValue)
        {
            if (max <= 0) throw new ArgumentOutOfRangeException("max");

            return Next(0, max);
        }

        [ThreadStatic]
        private static Byte[] _buf;
        /// <summary>返回一个指定范围内的随机数</summary>
        /// <remarks>
        /// 调用平均耗时37.76ns,其中GC耗时77.56%
        /// </remarks>
        /// <param name="min">返回的随机数的下界(随机数可取该下界值)</param>
        /// <param name="max">返回的随机数的上界(随机数不能取该上界值)</param>
        /// <returns></returns>
        public static Int32 Next(Int32 min, Int32 max)
        {
            if (max <= min) throw new ArgumentOutOfRangeException("max");

            if (_buf == null) _buf = new Byte[4];
            _rnd.GetBytes(_buf);

            var n = BitConverter.ToInt32(_buf, 0);
            if (min == Int32.MinValue && max == Int32.MaxValue) return n;
            if (min == 0 && max == Int32.MaxValue) return Math.Abs(n);
            if (min == Int32.MinValue && max == 0) return -Math.Abs(n);

            var num = max - min;
            // 不要进行复杂运算,看做是生成从0到(max-min)的随机数,然后再加上min即可
            return (Int32)((num * (UInt32)n >> 32) + min);
        }

        /// <summary>返回指定长度随机字节数组</summary>
        /// <remarks>
        /// 调用平均耗时5.46ns,其中GC耗时15%
        /// </remarks>
        /// <param name="count"></param>
        /// <returns></returns>
        public static Byte[] NextBytes(Int32 count)
        {
            var buf = new Byte[count];
            _rnd.GetBytes(buf);
            return buf;
        }

        /// <summary>返回指定长度随机字符串</summary>
        /// <param name="length">长度</param>
        /// <param name="symbol">是否包含符号</param>
        /// <returns></returns>
        public static String NextString(Int32 length, Boolean symbol = false)
        {
            var sb = Pool.StringBuilder.Get();
            for (var i = 0; i < length; i++)
            {
                var ch = ' ';
                if (symbol)
                    ch = (Char)Next(' ', 0x7F);
                else
                {
                    var n = Next(0, 10 + 26 + 26);
                    if (n < 10)
                        ch = (Char)('0' + n);
                    else if (n < 10 + 26)
                        ch = (Char)('A' + n - 10);
                    else
                        ch = (Char)('a' + n - 10 - 26);
                }
                sb.Append(ch);
            }

            return sb.Put(true);
        }
    }
}