0と1の間のランダムフロートを生成します


84

0から1の間の乱数を生成しようとしています。について読み続けてarc4random()いますが、フロートを取得するための情報がありません。どうすればよいですか?


1
重複ではなく、これがフロートに明示的に関係する唯一の質問のようです。
p i

回答:


139

[0、1 [のランダム値(0を含み、1を除く):

double val = ((double)arc4random() / UINT32_MAX);

ここでもう少し詳細。

上限が(double)0xFFFFFFFF / 0x100000000であるため実際の範囲は[ 0、0.9999999999767169356]です。


ありがとうございました。私が見た中で最も率直な答え。私はあなたのリンクを読み、これに関する追加の詳細を取得します。再度、感謝します。
jini 2011年

3
ARC4RANDOM_MAX手動で定義する必要があるのは奇妙ですが、0x1000000004294967296ですULONG_MAX + 1。とにかくarc4random()の最大値はどこに文書化されていULONG_MAXますか?
bobobobo 2012

@ bobobobo、ここから:developer.apple.com/library/mac/#documentation/Darwin/Reference/…arc4random()関数は、0から(2 ** 32)-1の範囲の疑似乱数を返します
ウラジミール

8
実際には、値は0xFFFFFFFF、(2 ** 32)-1 == 0x100000000-0x1 == 0xFFFFFFFF == UINT32_MAXである必要があります。これは、リンクでJörgBühmannが現在述べているとおりです。
Josejulio 2014

1
このように生成された値は、均一に分散されることが保証されていません。
ケリン2015年

107
// Seed (only once)
srand48(time(0));

double x = drand48();

// Swift version
// Seed (only once)
srand48(Int(Date().timeIntervalSince1970))

let x = drand48()

drand48()およびerand48()関数は、区間[0.0、1.0]に均一に分散された、非負の倍精度浮動小数点値を返します。


19
これが最良の答えです。
John Riselvato 2013

答えを少しだけ更新する必要があるかもしれません。シードを使用して一度初期化する必要があるNSHipsterについて読みましたdrand48アップルのドキュメントでは、それが初期化されなければならないことを示唆しています。
dulaccc 2014

1
シードが必要なのは、このランダムジェネレーターに計算の開始点を与えるためです。これがないと、ランダムなシーケンスはアプリの起動間で常に同じになります。
Jovan Stankovic 2017

これが最良の答えです。
sabiland 2017年

この回答は、の最適な精度の回答ではありませんdouble。最高の精度を達成する方法については、stackoverflow.com / a / 34765674/1033581を参照してください。
・クール

16

Swift 4.2以降については、https://stackoverflow.com/a/50733095/1033581を参照してください。


以下は、ObjCとSwift4.1の正しい均一性と最適な精度に関する推奨事項です。

32ビット精度(最適 Float

[0、1]の一様ランダム値(0.0および1.0を含む)、最大32ビットの精度:

Obj-C

float val = (float)arc4random() / UINT32_MAX;

スイフト

let val = Float(arc4random()) / Float(UInt32.max)

次の場合に最適です。

  • Float(またはFloat32その仮数部24ビットの有効数字の精度を有します)

48ビット精度(非推奨)

drand48内部で使用arc4random_bufする)を使用すると、48ビットの精度を簡単に実現できます。ただし、drand48には欠陥があることに注意してください、シード要件と、52ビットすべてのダブル仮数をランダム化するのに最適でためにことに。

[0、1]の一様ランダム値、48ビット精度:

スイフト

// seed (only needed once)
srand48(Int(Date.timeIntervalSinceReferenceDate))
// random Double value
let val = drand48()

64ビット精度(Doubleおよびに最適Float80

[0、1]の一様ランダム値(0.0および1.0を含む)、最大64ビットの精度:

Swift、arc4randomへの2つの呼び出しを使用:

let arc4random64 = UInt64(arc4random()) << 32 &+ UInt64(arc4random())
let val = Float80(arc4random64) / Float80(UInt64.max)

Swift、arc4random_bufへの1回の呼び出しを使用:

var arc4random64: UInt64 = 0
arc4random_buf(&arc4random64, MemoryLayout.size(ofValue: arc4random64))
let val = Float80(arc4random64) / Float80(UInt64.max)

次の場合に最適です。

  • Double(またはFloat64その仮数部52ビットの有効数字の精度を有します)
  • Float80その仮数部64ビットの仮数精度を有します

ノート

他の方法との比較

範囲が境界の1つ(0または1)を除外している回答は、均一性バイアスの影響を受ける可能性が高いため、回避する必要があります。

  • を使用するとarc4random()、最高の精度は1 / 0xFFFFFFFF(UINT32_MAX)です。
  • を使用するとarc4random_uniform()、最高の精度は1 / 0xFFFFFFFE(UINT32_MAX-1)です。
  • rand()密かにarc4randomを使用して)を使用すると、最高の精度は1 / 0x7FFFFFFF(RAND_MAX)です。
  • random()密かにarc4randomを使用して)を使用すると、最高の精度は1 / 0x7FFFFFFF(RAND_MAX)です。

これは、単一の呼び出しで、より良いよりも32ビット精度を達成するために、数学的に不可能だarc4randomarc4random_uniformrandまたはrandom。したがって、上記の32ビットおよび64ビットのソリューションは、達成できる最善の方法である必要があります。


「Float80」は実際のiOSデバイスでは使用できません(シミュレーターでのみ機能します)。
・クール

10

この関数は、負のフロート範囲でも機能します。

float randomFloat(float Min, float Max){
    return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}

4
外部モジュラス演算。Min+(Max-Min)*((float)arc4random())/ULONG_MAX代わりに使用してください。(float)キャストはちょうどパラノイアです。
bobobobo 2012

@boboboboは、外部モジュラスに同意しますが、ULONG_MAX(64ビットで18446744073709551615)ではなくUINT32_MAX(常に4294967295)で除算することをお勧めします。
・クール


1
(float)rand() / RAND_MAX

「rand()」だけを述べた以前の投稿は正しくありませんでした。これは、rand()を使用する正しい方法です。

これにより、0-> 1の間の数値が作成されます

BSDドキュメント:

rand()関数
は、0からRAND_MAXの範囲の疑似乱数整数のシーケンスを計算します(ヘッダーファイル "stdlib.h"で定義されています)。


1

これは、Float乱数Swift3.1の拡張機能です。

// MARK: Float Extension

public extension Float {

    /// Returns a random floating point number between 0.0 and 1.0, inclusive.
    public static var random: Float {
        return Float(arc4random()) / Float(UInt32.max))
    }

    /// Random float between 0 and n-1.
    ///
    /// - Parameter n:  Interval max
    /// - Returns:      Returns a random float point number between 0 and n max
    public static func random(min: Float, max: Float) -> Float {
        return Float.random * (max - min) + min
    }
}

@Cœurありがとうございます変更します
YannSteph 2017

1

Swift 4.2

Swift 4.2には、ネイティブでかなりフル機能の乱数APIが標準ライブラリに含まれています。(Swift EvolutionプロポーザルSE-0202

let intBetween0to9 = Int.random(in: 0...9) 
let doubleBetween0to1 = Double.random(in: 0...1)

すべての数値タイプには、範囲を取得して指定された範囲の乱数を返す静的random(in :)関数があります。


0

これを使用して、arc4random()の上限に関する問題を回避します。

u_int32_t upper_bound = 1000000;

float r = arc4random_uniform(upper_bound)*1.0/upper_bound;

MAC_10_7、IPHONE_4_3以降に適用できることに注意してください。


これには根本的な範囲の問題があります。upper_boundを10に設定すると、arc4random_uniformは0から9の値を返し、最終結果は0.0000から0.9000になります。代わりに、で割る必要がありupper_bound-1ます。それでも、upper_boundが原因で精度が任意に低くなるため、upper_boundをUINT32_MAXに増やす必要があります。また、のarc4random()*1.0 / UINT32_MAX代わりにを使用すると、さらに高い精度を得ることができますarc4random_uniform(UINT32_MAX)*1.0 / (UINT32_MAX-1)
・クール

-1

arc4random 最大範囲は0x100000000(4294967296)

これは、0から1までの乱数を生成するためのもう1つの優れたオプションです。

srand48(time(0));      // pseudo-random number initializer.
double r = drand48();

arc4randomの最大値は0xFFFFFFFF
Cœur 2017

ありがとう@Cœur..maxval0xFFFFFFFF私は知りませんでした
Gurunatha Dogi 2017

あなたの解決策もヨヴァン・スタンコビッチの答えと同じです。
・クール

ああ、私はそれを見ませんでした@
Cœur– Gurunatha Dogi 2017

-4
float x = arc4random() % 11 * 0.1;

これにより、0と1の間にランダムなフロートが生成されます 。詳細はこちら


3
注:11個の離散値のみを提供します:
0.0、0.1、0.2

8
はい、モジュラス演算はarc4random()の結果を0から10の間にカットし、それを10で除算します。この答えは一般的な使用には本当に悪いです。
bobobobo 2012

-4
rand() 

デフォルトでは、0から1の間の乱数(float)が生成されます。


4
これにより、ランダムなintが生成されます。
AlexQueue 2013年

rand()iOSには存在しないようで、存在する場合は、他のすべての* NIXと同じように整数を生成します。
jscs 2013

2
@JoshCaswellrand()はCの一部であり、CはObjective-C(iOSプログラミングで使用されます)の一部です。C関数rand()はiOSに絶対に存在しますが、arc4random()推奨されます。
frungi 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.