产生的随机数不随机怎么办?



你用过.net的System.Random类吗?.用过的人会发现随机数生成器类不能很好的产生随机数,而且性能不太好。用随机数生成器类的用途很多,但由于System.Random不太好的表现给我们造成了很大的不便。为了解决这个问题我们可以重新写一个产生随机数类来弥补System.Random的不足之处。

  首先我们现在重写一个System.Random的基类RdomBase,它将实现System.Random中所实现的所有方法,但我们将保留Next()方法作为抽象方法,以便继承类根据不同的运算规则来实现它。在随机数生成器类中编写了几个有用的类型转换方法以备读者需要时使用。基类RdomBase的代码如下:

public abstract class RdomBase: Random
{
  #region 构造函数
  public RdomBase()
  {
  }

  public RdomBase(int seed) : base(seed)//执行基类构造方法
  {
  }
  #endregion



  #region 方法
  protected int GetBaseNextInt32()//获取下一个32位整数的随机数
  {
    return base.Next();
  }

  protected uint GetBaseNextUInt32() //获取下一个32位无符号整数的随机数

  {
    return ConvertToUInt32(base.Next());
  }

  protected double GetBaseNextDouble() //获取下一个双精度的随机数
  {
    return base.NextDouble();
  }
  #endregion

  #region 重写
  public abstract override int Next();//重写定义为抽象方法

  public override int Next(int maxValue) //重写方法
  {
    return Next(0, maxValue);
  }

  public override int Next(int minValue, int maxValue) //重写方法
  {
    return Convert.ToInt32((maxValue - minValue) * Sample() + minValue);
  }

  public override double NextDouble() //重写方法
  {
    return Sample();
  }


  public override void NextBytes(byte[] buffer)//计算方法具体介绍见 http://www.qbrundage.com/michaelb/pubs/essays/random_number_generation.html
  {
    int i, j, tmp;

    // fill the part of the buffer that can be covered by full Int32s

    for (i = 0; i < buffer.Length - 4; i += 4)
    {
        tmp = Next();
        buffer =Convert.ToByte(tmp & 0x000000FF);

        buffer[i + 1]=Convert.ToByte((tmp & 0x0000FF00) >> 8);

        buffer[i + 2]=Convert.ToByte((tmp & 0x00FF0000) >> 16);

        buffer[i + 3]=Convert.ToByte((tmp & 0xFF000000) >> 24);

    }

    tmp = Next();
    // fill the rest of the buffer
    for (j = 0; j < buffer.Length % 4; j++)
    {
        buffer[i + j] = Convert.ToByte(((tmp & (0x000000FF << (8 * j))) >> (8 * j)));
    }
  }



  protected override double Sample()
  {
    // 在[0,1)范围产生一个随机数
    return Convert.ToDouble(Next()) / 2147483648.0; // 除以正整数2^31
  }
  #endregion

  #region Utility Methods
  protected static UInt32 ConvertToUInt32(Int32 value)
  {
    return BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
  }

  protected static Int32 ConvertToInt32(UInt32 value)
  {
    return BitConverter.ToInt32(BitConverter.GetBytes(value), 0);
  }

  protected static Int32 ConvertToInt32(UInt64 value)
  {
    return BitConverter.ToInt32(BitConverter.GetBytes(value & 0x000000007fffffff) , 0);
  }
  #endregion

}


  我们再做一个NewRandom类,它从上边的类继承而来,在这个类里我们实现Next()的抽象方法。代码如下:

public class NewRandom : RdomBase
{

  #region 构造函数
  public NewRandom() : this(Convert.ToInt32(DateTime.Now.Ticks & 0x000000007FFFFFFF)) { }

  public NewRandom(int seed): base(seed)
  {
    i = Convert.ToUInt64(GetBaseNextInt32());
  }
  #endregion



  #region 私有成员
  private static readonly uint a = 1099087573;
  private ulong i=1;
  #endregion



  #region 方法
  public override int Next()//重写父类抽象方法
  {
    #region Execution
    i = a * i; // overflow occurs here!
    return ConvertToInt32(i);
    #endregion
  }
  #endregion
}

  现在所有代码都介绍完了,读者可以把代码嵌入到自己的程序里试验一下这个随机数生成器类,比如在程序里写段如下代码:
private NewRandom m_NewRandom;
m_NewRandom = new RandomNumberGeneration.NewRandom();
m_NewRandom.NextDouble();

  试验后你是否感觉到用起来比System.Random爽快、好用?当然这只是一种思路,读者可以根据自己的情况调整以上代码来达到更适合自己程序的随机数生成器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值