0

私は Objective C が初めてで、理解しようとしていますarc4random()

ウェブ上には相反する説明がたくさんあります。私の混乱を解消してください。次のうち正しいものはどれですか。

// 1.
 arc4random() % (toNumber - fromNumber) + fromNumber;

また

//2.
arc4random() % ((toNumber - fromNumber) + 1) + fromNumber; 

//toNumber-fromNumbers are any range of numbers like random # between 7-90.
4

2 に答える 2

6

このコードは、7 から 90 までの乱数を取得します。

NSUInteger random = 7 + arc4random_uniform(90 - 7);

arc4random_uniformモジュロ バイアスを回避するために使用します。

于 2013-03-11T16:32:05.913 に答える
4

アダムの答えは正しいです。ただし、2 つの違いを明確にするために、2 番目のものは可能な範囲を 1 つ上げて、範囲を包括的にします。覚えておくべき重要なことは、モジュロは剰余除算であるため、toNumber可能な結果はあるものの、そのうちの 1 つがゼロ ( の結果arc4random()が の倍数である場合toNumber) であり、toNumberそれ自体が剰余になることはありません。

// 1.
 arc4random() % (10 - 5) + 5;

この結果、範囲は0 + 5から4 + 5、つまり 5 から 9 になります。

//2.
arc4random() % ((10 - 5) + 1) + 5; 

これにより、0 + 5からの範囲が得られ(4 + 1) + 5ます。これは 5 から 10 です。

modulo を使用する場合、どちらも正しくも正しくもありません。1 つは上限範囲を含まず、もう 1 つは上限範囲を含みます。ただし、剰余除算がどのように機能するかを考え、PRNG によって返される数値のプールをサイクル全体の範囲の長さで考えると、範囲が最大範囲の最大範囲に均等に分割されない場合に気付くでしょう。偏った結果が得られるプール。たとえば、arc4random()が 1 ~ 5 の結果を返した場合 (明らかにそうではありません)、0 ~ 2 の数値が必要で、 を使用した場合arc4random() % 3、これらは可能な結果です。

1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2

2 つの 1 と 2 つの 2 がありますが、0 は 1 つだけであることに注意してください。これは、3 の範囲が PRNG の 5 の範囲に均等に分割されないためです。その結果、(滑稽なことに)PRNG range % desired rangeサイクルの最後の数字は「偏っている」ため、選別する必要があります。数字自体はそうではありません。本当に偏っていますが、最後から選別する方が簡単です。これを行わないと、範囲の低い数値が表示される可能性が高くなります。

生成できる数値の上限を計算し、それを目的の範囲でモジュロして、それらの数値を最後から引き出すことで、数値を選別できます。「それらの数字を最後から引き出す」とは、「最後の数字ではない数字が得られるまで無限にループする」ことを意味します。

それは悪い習慣だと言う人もいます。理論的には永久にループできます。ただし、実際には、モジュロ バイアスが PRNG の数のプールの半分を超えることはないため (通常はそれよりはるかに少ない)、予想される再試行回数は常に 1 未満です。rand私はかつて、この手法を使用するためのラッパーを書きました。

この例は、OpenBSD のソースで見ることができます。ここでは、番号がクリーンであると判断されるまでarc4random_uniform呼び出しがループします。arc4random

于 2013-03-11T18:25:12.990 に答える