【问题标题】:What's the performance hit for accessing a static random instance [duplicate]访问静态随机实例对性能有何影响[重复]
【发布时间】:2012-12-27 08:51:21
【问题描述】:

可能重复:
Random number generator only generating one random number
class System.Random .. why not static?

我有一个名为 RandomGenerator 的公共静态类,它只有一个值 public static random = new Random();

这就是它的样子

    public static class RandomGenerator
    {
        public static Random random = new Random(); 
    }

我必须这样做,因为当我的代码访问随机数时,它会生成太多重复副本(我相信这与 Random 在内存中的位置有关)

上面的代码效果很好!我的代码每次调用时都会生成一个真正的随机值。我的问题是为什么随机不是 C# 语言的内置静态函数?是因为以这种方式访问​​某些东西会导致性能下降吗?我编写代码的方式是否存在明显的性能问题?

【问题讨论】:

  • 离题:似乎每隔一段时间有人遇到他们不理解的设计决策并询问 SO,“性能”是他们最好的猜测。 为什么?
  • 更具体地说,每次调用它都会返回一个Random 的实例。要获取随机值,您无需创建新实例。只需调用Next 方法之一
  • @delnan,可能是因为它是代码启动时唯一明显的问题......即静态方法/属性测试起来非常痛苦(因此可能导致性能问题)这一事实很难预期,而每个人都看到程序很慢......
  • @AlexeiLevenkov 但这不仅仅是关于static 或任何其他单一问题。它无处不在。每个人都在做这样的 API,我也应该这样做吗?当然,性能上存在重要差异。 -- 为什么 C++ 需要分号?是为了表演吗? ——为什么圆是圆的?它对性能有帮助吗?
  • @delnan 那是不必要的。事实上,正如我在问题中解释的那样,我确实了解为什么我想做这样的事情背后的设计方面。我不明白为什么在 C# 中没有一个类为我做这件事,我推测这可能是因为它导致了某种类型的性能问题。我现在知道情况并非如此,这要归功于 SO 更有帮助的成员。感谢您完全没有建设性的评论,它已被标记。

标签: c# oop class random static


【解决方案1】:

MSDN 写了以下关于 Random 构造函数的内容:

默认种子值来自系统时钟,具有有限的 解析度。结果,在 通过调用默认构造函数的紧密继承将具有 相同的默认种子值,因此,将产生相同的 随机数集。这个问题可以通过使用单个 随机对象生成所有随机数。你也可以解决 它通过修改系统时钟返回的种子值,然后 将这个新的种子值显式地提供给 Random(Int32) 构造函数。

http://msdn.microsoft.com/en-us/library/h343ddh9.aspx

【讨论】:

  • 我应该看看 MSDN 文档,这将是我下次的第一站。这正是我想要的,谢谢。
【解决方案2】:

您所描述的问题与随机或非静态无关。我想您正在创建 Random 实例,然后从该实例中获取随机值。这样,每个 Random 都是使用默认种子创建的,默认种子是当前时间,具有秒精度。由于 Random 实例是使用相同的种子创建的,因此在几秒钟内您获得了相同的值。

【讨论】:

  • 不是只有一个实例吗?
  • @delnan Random 不是单例。
  • 但是RandomGenerator.randomstatic
  • @delnan 当你有静态实例时,你会在调用 Next 时得到不同的值
  • 哦,您是在解释为什么他在不断创建新的Random 实例时总是得到相同的数字?在这种情况下,您的回答是有道理的,但不符合问题。
【解决方案3】:

它本身不是静态的,因为 .Net 中的“随机”数字并不是真正随机的——它们是“伪随机”,这意味着它们对于统计来说足够随机,但对于密码学来说不够随机。也就是说,它们均匀分布在一个范围内,但给定种子参数,您可以预测下一个“随机”值将是什么。这就是为什么您必须实例化 Random 类(就像您在上面所做的那样)以获得随机数 - 您需要创建一个新实例,为其播种(如果您不手动播种,它会使用当前时间戳) ),然后得到“下一个”随机值。如果您使用相同的值作为 Random 类的种子,它将产生相同系列的“随机”数字 - 使用系统时间作为种子非常有效,因为它总是在变化,但很容易猜到。

拥有像这样的静态“随机”类是获得随机值的一种方法,无需在每次需要时都实例化新对象,但您在这里所做的只是实例化一个新副本。一种更有效地做到这一点的方法可能是这样的:

类随机数 { 静态只读随机 r = new Random();

    public static Int32 GetNext(int maxValue)
    {
        return r.Next(maxValue);
    }

    public static Int32 GetNext()
    {
        return r.Next();
    }
}

这样,您只需实例化一次,并且您将继续重用该实例 - 每次您想要一个新的随机数时,只需调用静态类的 GetNext 方法(指定或不指定上限) ,你会得到一个新号码。

【讨论】:

  • (1) 它们是 PRNGs 如何成为非静态的理由? (2) 你似乎自相矛盾。您提出这个问题是因为Random 不是静态的,但继续说是解决问题的一种方法(并且没有说出任何其他缺点)。
  • Random 本身并不是静态的,它是实例化的——我会澄清我的答案。
  • 我不认为部分不清楚。
  • 谢谢,这是一个非常好的答案。
  • @delnan:也许这就是我的设计知识崩溃的地方——我一直觉得“随机”不是静态的,以迫使开发人员承认它的非随机性,但也许这不是这个案子,还有其他一些设计决定的原因。在 VB 类中,您可以只使用 Rand,它会获取一个新的随机数,尽管您可以选择手动播种生成器(我知道这不是一个完美的例子) - 为什么要更改为 .NET?既然随机种子本身与系统时间一样,为什么它不能作为一个静态的、本机地做这里正在做的事情?
猜你喜欢
  • 2015-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-13
  • 2023-01-27
  • 2015-03-04
  • 1970-01-01
相关资源
最近更新 更多