weixin_39813541
四次元口袋
采纳率0%
2019-07-24 17:18 阅读 1.1k

随机数生成器只生成一个随机数

有以下函数:

//Function to get random numberpublic static int RandomNumber(int min, int max){
    Random random = new Random();
    return random.Next(min, max);}

不知道怎么描述:

byte[] mac = new byte[6];for (int x = 0; x < 6; ++x)
    mac[x] = (byte)(Misc.RandomNumber((int)0xFFFF, (int)0xFFFFFF) % 256);

如果在运行时使用调试器单步执行该循环,则会得到不同的值(这正是我想要的)。 但是,如果将断点放在该代码之下两行,则“ mac”数组的所有成员的值都相等。
为什么会这样?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

5条回答 默认 最新

  • C_SESER C_SESER 2019-07-25 02:04

    这个不是python呀……

    但问题肯定出在两点:
    1. seed种子的问题,如果是拿时间作为seed,时间间隔太短,数组里的数字肯定是一样的
    2. 这种问题的种子问题不应该你自己解决,去查查api,一定是有专门生成某个区间内n个数的随机数的函数

    点赞 评论 复制链接分享
  • weixin_38166411 weixin_38166411 2019-07-25 10:12

    每次你做新的 new Random()时,它都会使用时钟进行初始化。这意味着在一个严格的循环中,您可以多次得到相同的值。您应该保持一个 Random ,并在同一个上继续使用 Next。

    //Function to get a random number private static readonly Random random = new Random(); private static readonly object syncLock = new object(); public static int RandomNumber(int min, int max){
        lock(syncLock) { // synchronize
            return random.Next(min, max);
        }}
    

    为什么这儿需要lock?
    基本上,Next 将更改 Random 实例的内部状态。 如果我们同时在多个线程中这样做,你可能会说“我们只是让结果变得更随机了” ,但实际上我们所做的可能会破坏内部实现,我们也可能开始从不同的线程获得相同的数字,这可能是一个问题,也可能不是。 但是,内部发生的情况的保证是更大的问题; 因为 Random 并不能保证线程安全。 因此,有两种有效的方法:
    • 同步,这样我们就不会同时从不同的线程访问它
    使用不同的Random
    lock 实现了这些方法中的第一种(也是更简单的) ; 然而,另一种方法可能是:
    private static readonly ThreadLocal appRandom
    = new ThreadLocal(() => new Random());
    这是针对每个线程的,所以你不需要同步。

    点赞 评论 复制链接分享
  • weixin_38166435 weixin_38166435 2019-07-25 10:20

    为了便于在整个应用程序中重用,static类可能会有用。

    public static class StaticRandom{
        private static int seed;
        private static ThreadLocal<Random> threadLocal = new ThreadLocal<Random>
            (() => new Random(Interlocked.Increment(ref seed)));
        static StaticRandom()
        {
            seed = Environment.TickCount;
        }
        public static Random Instance { get { return threadLocal.Value; } }}
    

    然后可以使用static 随机实例和代码,如

    StaticRandom.Instance.Next(1, 100);
    
    点赞 评论 复制链接分享
  • weixin_38166163 weixin_38166163 2019-07-25 10:29

    可以通过使用特定于线程的存储模式来避免同步:

    public class RandomNumber : IRandomNumber{
        private static readonly Random Global = new Random();
        [ThreadStatic] private static Random _local;
        public int Next(int max)
        {
            var localBuffer = _local;
            if (localBuffer == null) 
            {
                int seed;
                lock(Global) seed = Global.Next();
                localBuffer = new Random(seed);
                _local = localBuffer;
            }
            return localBuffer.Next(max);
        }}
    
    点赞 评论 复制链接分享
  • weixin_38166347 weixin_38166347 2019-07-25 10:36

    正确的解决方案:

    namespace mySpace{
        public static class Util
        {
            private static rnd = new Random();
            public static int GetRandom()
            {
                return rnd.Next();
            }
        }}
    

    所以:

    var i = Util.GetRandom();
    

    也可以依赖 Guid。

    public static class Util{
        public static int GetRandom()
        {
            return Guid.NewGuid().GetHashCode();
        }}
    

    它会稍微慢一点,但是可以比Random.Next更随机。 接下来
    但不是:

    new Random(Guid.NewGuid().GetHashCode()).Next();
    

    不必要的对象创建会使它变慢,特别是在循环下。
    永远别这样:

    new Random().Next();
    

    它不仅速度较慢(在一个循环中) ,而且它的随机性...... 并不是很好。

    点赞 评论 复制链接分享

相关推荐