web-dev-qa-db-ja.com

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

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

82
jini

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

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

もう少し詳細 こちら

実際の範囲は[0、0.999999999767169356]です。上限は(double)0xFFFFFFFF/0x100000000です。

134
Vladimir
// 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]に均一に分布した、負ではない倍精度の浮動小数点値を返します。

105
Jovan Stankovic

Swift 4.2+を参照: https://stackoverflow.com/a/50733095/1033581


以下は、ObjCおよびSwift 4.1。

32ビット精度(Floatに最適)

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

Obj-C

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

Swift

_let val = Float(arc4random()) / Float(UInt32.max)
_

以下に最適です。

  • 仮数に24ビットの仮数精度を持つFloat(または_Float32_)

48ビット精度(非開示)

_drand48_( フードの下で_arc4random_buf_を使用 )を使用すると、48ビットの精度を簡単に達成できます。しかし drand48には欠陥 があることに注意してください。これはシード要件のためであり、Double仮数の52ビットすべてをランダム化するために準最適であるためです。

[0、1]の一様乱数値、48ビット精度:

Swift

_// 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)
_

以下に最適です。

  • 仮数の有効桁数が52ビットのDouble(または_Float64_)
  • 仮数に64ビットの仮数精度を持つ_Float80_

ノート

他の方法との比較

範囲が境界の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)

_arc4random_、_arc4random_uniform_、Rand、またはrandomの1回の呼び出しで32ビットを超える精度を達成することは数学的に不可能です。したがって、上記の32ビットおよび64ビットのソリューションは、達成可能な最高のものでなければなりません。

15
Cœur

この関数は負の浮動小数点範囲でも機能します:

float randomFloat(float Min, float Max){
    return ((arc4random()%Rand_MAX)/(Rand_MAX*1.0))*(Max-Min)+Min;
}
10
Héctor Sanchez

Swift 4.2+

Swift 4.2は、範囲内のランダムな値のネイティブサポートを追加します。

_let x = Float.random(in: 0.0...1.0)
let y = Double.random(in: 0.0...1.0)
let z = Float80.random(in: 0.0...1.0)
_

Doc:

4
Cœur

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:) 関数があり、範囲を取得し、指定された範囲の乱数を返します。

1
Suhit Patil
(float)Rand() / Rand_MAX

「Rand()」だけを記載した以前の投稿は間違っていました。これは、Rand()を使用する正しい方法です。

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

BSDドキュメント:

Rand()関数は、擬似乱数整数のシーケンスを計算します
0〜Rand_MAXの範囲(ヘッダーファイル「stdlib.h」で定義)。

1
Leslie Godwin

これはフロート乱数の拡張ですSwift 3.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
    }
}
1
YannSteph

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

u_int32_t upper_bound = 1000000;

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

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

0
malex