回答:
arc4random_uniform()
関数を使用する必要があります。それはに優れたアルゴリズムを使用しrand
ます。シードを設定する必要すらありません。
#include <stdlib.h>
// ...
// ...
int r = arc4random_uniform(74);
arc4random
manページ:
NAME arc4random, arc4random_stir, arc4random_addrandom -- arc4 random number generator LIBRARY Standard C Library (libc, -lc) SYNOPSIS #include <stdlib.h> u_int32_t arc4random(void); void arc4random_stir(void); void arc4random_addrandom(unsigned char *dat, int datlen); DESCRIPTION The arc4random() function uses the key stream generator employed by the arc4 cipher, which uses 8*8 8 bit S-Boxes. The S-Boxes can be in about (2**1700) states. The arc4random() function returns pseudo- random numbers in the range of 0 to (2**32)-1, and therefore has twice the range of rand(3) and random(3). The arc4random_stir() function reads data from /dev/urandom and uses it to permute the S-Boxes via arc4random_addrandom(). There is no need to call arc4random_stir() before using arc4random(), since arc4random() automatically initializes itself. EXAMPLES The following produces a drop-in replacement for the traditional rand() and random() functions using arc4random(): #define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))
arc4random_uniform(upper_bound)
関数を使用して、範囲内の乱数を生成します。以下は、0から73までの数値を生成します。
arc4random_uniform(74)
arc4random_uniform(upper_bound)
manページで説明されているように、モジュロバイアスを回避します。
arc4random_uniform()は、upper_boundより小さい均一に分布した乱数を返します。上限が2のべき乗でない場合に「モジュロバイアス」を回避するため、「arc4random()%upper_bound」のような構成よりもarc4random_uniform()をお勧めします。
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_3
があります。チェックに失敗した場合は、別のソリューションにフォールバックしてください。
Cと同じように
#include <time.h>
#include <stdlib.h>
...
srand(time(NULL));
int r = rand() % 74;
(あなたがあなたのJavaの例がすることである0を含むが74を除くことを意味すると仮定して)
編集:フィールを代用して自由random()
またはarc4random()
のためにrand()
(他の人が指摘したように、ある、かなり嫌)。
多くのプロジェクトで使用する方法を追加できると思いました。
- (NSInteger)randomValueBetween:(NSInteger)min and:(NSInteger)max {
return (NSInteger)(min + arc4random_uniform(max - min + 1));
}
多くのファイルでそれを使用してしまう場合、通常は次のようにマクロを宣言します。
#define RAND_FROM_TO(min, max) (min + arc4random_uniform(max - min + 1))
例えば
NSInteger myInteger = RAND_FROM_TO(0, 74) // 0, 1, 2,..., 73, 74
注:iOS 4.3 / OS X v10.7(Lion)以降のみ
これにより、0〜47の浮動小数点数が得られます。
float low_bound = 0;
float high_bound = 47;
float rndValue = (((float)arc4random()/0x100000000)*(high_bound-low_bound)+low_bound);
または単に
float rndValue = (((float)arc4random()/0x100000000)*47);
下限と上限の両方が負になることもあります。以下のサンプルコードは、-35.76から+12.09の間の乱数を提供します。
float low_bound = -35.76;
float high_bound = 12.09;
float rndValue = (((float)arc4random()/0x100000000)*(high_bound-low_bound)+low_bound);
結果を丸め整数値に変換します。
int intRndValue = (int)(rndValue + 0.5);
rand(3)のマニュアルページによると、rand(3)関数のrandファミリは、random(3)によって廃止されました。これは、rand()の下位12ビットが循環パターンを通過するためです。乱数を取得するには、符号なしシードでsrandom()を呼び出してジェネレータをシードし、次にrandom()を呼び出します。したがって、上記のコードと同等のものは
#import <stdlib.h>
#import <time.h>
srandom(time(NULL));
random() % 74;
シードを変更したくない場合を除いて、プログラムで一度だけsrandom()を呼び出す必要があります。真にランダムな値については説明したくないとおっしゃいましたが、rand()はかなり悪い乱数ジェネレータであり、random()は0とRAND_MAXの間の数を生成するため、依然としてモジュロバイアスの影響を受けます。したがって、たとえばRAND_MAXが3で、0と2の間の乱数が必要な場合、1や2よりも2倍の確率で0を取得します。
使いやすい arc4random_uniform
。ただし、これはiOS 4.3以下では使用できません。幸い、iOSはこのシンボルをコンパイル時ではなく実行時にバインドします(そのため、#ifプリプロセッサディレクティブを使用して、それが使用可能かどうかを確認しないでください)。
arc4random_uniform
利用可能かどうかを判断する最良の方法は、次のようなことです。
#include <stdlib.h>
int r = 0;
if (arc4random_uniform != NULL)
r = arc4random_uniform (74);
else
r = (arc4random() % 74);
私は、JavaでMath.random()のように機能するものを作成するために、独自の乱数ユーティリティクラスを作成しました。機能は2つだけで、すべてCで作成されています。
ヘッダーファイル:
//Random.h
void initRandomSeed(long firstSeed);
float nextRandomFloat();
実装ファイル:
//Random.m
static unsigned long seed;
void initRandomSeed(long firstSeed)
{
seed = firstSeed;
}
float nextRandomFloat()
{
return (((seed= 1664525*seed + 1013904223)>>16) / (float)0x10000);
}
これは、疑似ランダムを生成するかなり古典的な方法です。私のアプリデリゲートで私は電話します:
#import "Random.h"
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
initRandomSeed( (long) [[NSDate date] timeIntervalSince1970] );
//Do other initialization junk.
}
その後、私はただ言う:
float myRandomNumber = nextRandomFloat() * 74;
このメソッドは0.0f(両端を含む)〜1.0f(両端を含まない)の乱数を返すことに注意してください。
iOS 9およびOS X 10.11では、新しいGameplayKitクラスを使用して、さまざまな方法で乱数を生成できます。
選択できるソースタイプは4つあります。一般的なランダムソース(名前なし、システムが何をするかを選択する)、線形合同、ARC4、およびMersenne Twisterです。これらはランダムな整数、浮動小数点数、ブール値を生成できます。
最も単純なレベルでは、次のようにシステムの組み込みランダムソースから乱数を生成できます。
NSInteger rand = [[GKRandomSource sharedRandom] nextInt];
-2,147,483,648〜2,147,483,647の数値が生成されます。0と上限(排他的)の間の数値が必要な場合は、次のようにします。
NSInteger rand6 = [[GKRandomSource sharedRandom] nextIntWithUpperBound:6];
GameplayKitには、サイコロを操作するための便利なコンストラクタがいくつか組み込まれています。たとえば、次のように6面のサイコロを振ることができます。
GKRandomDistribution *d6 = [GKRandomDistribution d6];
[d6 nextInt];
さらに、などを使用してランダム分布を形成できますGKShuffledDistribution
。
ゲーム開発者にとっては、random()を使用してランダムを生成します。おそらく、arc4random()を使用するよりも少なくとも5倍高速です。random()の全範囲を使用してランダムを生成する場合、モジュロバイアスは特にゲームでは問題になりません。必ず最初にシードしてください。AppDelegateでsrandomdev()を呼び出します。ここにいくつかのヘルパー関数があります:
static inline int random_range(int low, int high){ return (random()%(high-low+1))+low;}
static inline CGFloat frandom(){ return (CGFloat)random()/UINT32_C(0x7FFFFFFF);}
static inline CGFloat frandom_range(CGFloat low, CGFloat high){ return (high-low)*frandom()+low;}
arc4random_uniform(x)
@yoodによる以下の説明に従って使用してください。これはstdlib.h(OS X 10.7およびiOS 4.3以降)にもあり、乱数のより均一な分布を提供します。使用法int r = arc4random_uniform(74);