为啥 c# 中的 Random 构造函数在方法末尾分配 Seed 参数?

Posted

技术标签:

【中文标题】为啥 c# 中的 Random 构造函数在方法末尾分配 Seed 参数?【英文标题】:Why Random constructor in c# assigns Seed parameter in the end of the method?为什么 c# 中的 Random 构造函数在方法末尾分配 Seed 参数? 【发布时间】:2017-11-25 17:03:15 【问题描述】:

我检查了 .Net here 的 Random 类的源代码。让我吃惊的是最后一行

  public Random(int Seed) 
    int ii;
    int mj, mk;

    //Initialize our Seed array.
    //This algorithm comes from Numerical Recipes in C (2nd Ed.)
    int subtraction = (Seed == Int32.MinValue) ? Int32.MaxValue : Math.Abs(Seed);
    mj = MSEED - subtraction;
    SeedArray[55]=mj;
    mk=1;
    for (int i=1; i<55; i++)   //Apparently the range [1..55] is special (Knuth) and so we're wasting the 0'th position.
      ii = (21*i)%55;
      SeedArray[ii]=mk;
      mk = mj - mk;
      if (mk<0) mk+=MBIG;
      mj=SeedArray[ii];
    
    for (int k=1; k<5; k++) 
      for (int i=1; i<56; i++) 
    SeedArray[i] -= SeedArray[1+(i+30)%55];
    if (SeedArray[i]<0) SeedArray[i]+=MBIG;
      
    
    inext=0;
    inextp = 21;
    Seed = 1;
  

在方法的最后赋值参数的目的是什么?

【问题讨论】:

为什么不呢?我不知道他们为什么选择这样做,但我也看不出为什么不这样做。 @LasseV.Karlsen 为什么不呢?因为它什么都不做。 我现在看到了,我错误地认为它是一个正在设置的属性,我现在看到它是参数。 确实,套管让你离开这里,但它真的没有用。猜猜这是一个实习生写的代码;) //这个算法来自Numerical Recipes in C (2nd Ed.) - 也许最后一行是*seed = 1; - 我检查过 - 它是 - 它是一个下降在副本中进行了一些调整。 【参考方案1】:

这是对书 Numerical Recipies in C (2nd Edition)(第 283 页)中的 float rand3(long *idum) 函数的错误翻译。有这部分初始化种子数组(idum是种子参数):

iff=1;
mj=labs(MSEED-labs(*idum)); 
mj %= MBIG; large number MSEED.
ma[55]=mj;
mk=1;
for (i=1;i<=54;i++)  
    ii=(21*i) % 55;
    ma[ii]=mk; 
    mk=mj-mk;
    if (mk < MZ) mk += MBIG;
        mj=ma[ii];

for (k=1;k<=4;k++)
    (i=1;i<=55;i++)  
        ma[i] -= ma[1+(i+30) % 55];
       if (ma[i] < MZ) ma[i] += MBIG;
    
inext=0; 
inextp=31;
*idum=1;

翻译器没有将种子参数设置为ref。因此,该行在 C# 翻译中没有影响。

【讨论】:

【参考方案2】:

由于ref 没有传递Seed 参数并且int 是一个值类型,所以最后一行没有任何作用。

感谢@Alex K 指出这一点,在检查了他们在C 中的数字食谱 中采用的算法之后,他们确实复制并粘贴了最后一行:

if ( * idum < 0 || iff == 0) 
  Initialization.
  iff = 1;
  mj = labs(MSEED - labs( * idum));
  Initialize ma[55] using the seed idum and the
  mj %= MBIG;
  large number MSEED.
  ma[55] = mj;
  mk = 1;
  for (i = 1; i <= 54; i++) 
    ii = (21 * i) % 55;
    ma[ii] = mk;
    mk = mj - mk;
    if (mk < MZ) mk += MBIG;
    mj = ma[ii];
  
  for (k = 1; k <= 4; k++)
    (i = 1; i <= 55; i++) 
    ator.”
    ma[i] -= ma[1 + (i + 30) % 55];
    if (ma[i] < MZ) ma[i] += MBIG;
  
  inext = 0;
  inextp = 31;
  * idum = 1;

【讨论】:

我当然希望他们更多地关注加密随机的东西,而不是对这个有点尴尬的复制/粘贴工作。【参考方案3】:

在那里设置Seed 是没有用的。它是一个局部值类型变量,在构造函数结束后没有任何用处。

我想这只是一个错误。

【讨论】:

以上是关于为啥 c# 中的 Random 构造函数在方法末尾分配 Seed 参数?的主要内容,如果未能解决你的问题,请参考以下文章

C#和Java中的构造器constructor是啥?起啥作用?为啥不可以被override??

为啥 C# 3.0 对象初始值设定项构造函数括号是可选的?

为啥我不能在 C# 中使用基本构造函数 [重复]

c#中泛型类构造函数重载赋值时为啥不接受null?对其赋空值应给怎么做?

在 C# String 构造函数 String(Char*) 中,为啥构造函数不期望指向字符数组的指针?

C#中的多线程问题,为啥带参数的方法不行,不带参数的可以?