【问题标题】:How does one make random number between range for arc4random_uniform()?如何在 arc4random_uniform() 的范围之间生成随机数?
【发布时间】:2014-06-10 03:32:50
【问题描述】:

所以我在这个代码位中的目标是随机掷两个骰子,我们都知道你的普通骰子只有 6 个面,所以我导入了 Foundation 以访问 arc4random_uniform(UInt32)。我尝试使用 (1..7) 的范围来避免随机获得 0,但是这返回了一个我不太喜欢的错误。我试着这样做:

dice1 = arc4random_uniform(UInt32(1..7))

但是返回了

找不到接受所提供参数的“init”的重载

我希望这些信息足以让你们这些优秀的德布斯帮助我:)

请注意,我只是在操场上这样做以练习 swift。我不必学习如何做到这一点。在我开始构建实际应用程序之前,我只是在修补:D

//imports random number function
import Foundation
//creates data storage for dice roll
var dice1: UInt32 = 0
var dice2: UInt32 = 0
//counter variable
var i = 0
//how many times snake eyes happens
var snakeeyes = 0
 //how many times a double is rolled
var `double` = 0
//rolls dice 100 times
while i < 100{
    //from here
    //sets dice roll

这会返回一个错误'Range $T3' is not convertible to UInt32

   dice1 = arc4random_uniform(1..7)
   dice2 = arc4random_uniform(1..7)
    //checks for snake eyes
    if dice1 == 1 && dice2 == 1 {
        snakeeyes = snakeeyes + 1

    }
    //checks for doubles
    if dice1 == dice2{
        `double` = `double` + 1
    }
    //increases counter
        i = i + 1
    //to here
}
println("You got Snake Eyes \(snakeeyes) times.")
println("You got Doubles, \(`double`) times.")

【问题讨论】:

  • 我相信你应该使用dice1 = arc4random_uniform(6) + 1 来获得 1 - 6 的范围。不过,我不会做 iOS 目标 C,也没有任何关于 swift 语言的知识。 random 方法应该返回 0 - 5,而 + 1 将是 1 - 6。
  • Range 本身是一个对象数据,它不是整数数据,这就是为什么当参数只包含 (UInt32) 时出现错误的原因 - u_int32_t arc4random_uniform(u_int32_t upper_bound);
  • 啊哈!谢谢天空!做了一个断言来测试它是否小于 0,并且可以确认这正是我需要的,把它作为答案,这样我就可以检查它了!
  • probability = Int(arc4random_uniform(UInt32(total))) - 如果您有多个非特定的铸造投诉(因为预输入/标题不起作用)
  • 这是从 Swift 4.2 开始内置的,如下所述stackoverflow.com/a/50696901/1148030

标签: range swift arc4random


【解决方案1】:

我相信你应该这样做

dice1 = arc4random_uniform(6) + 1;

要获得 1 - 6 的范围。不过,我不做 iOS 目标 C,也没有任何关于 swift 语言的知识。 random 方法应该返回一个介于 0 和 5 之间的值,+1 将使它成为一个介于 1 和 6 之间的值。

如果你需要一个介于 10 - 30 之间的范围,那么就这样做

int random = arc4random_uniform(21) + 10;

【讨论】:

  • @JoeSmith 你完全正确,它应该是 arc4random_uniform(21)+10 返回 10 - 30 之间的范围,因为上限不包括在内。 “arc4random_uniform(20)+10”部分基于社区编辑和投票。
  • 是的,我刚刚测试并得到一个随机颜色(即想要一个介于 0 - 255 之间的随机值),我使用了:“arc4random_uniform(256) + 0”
【解决方案2】:

很多不错的答案,但我只是想分享一下我个人最喜欢的 Swift 正整数随机数生成函数:

斯威夫特 2

func randomNumber(range: Range<Int> = 1...6) -> Int {
    let min = range.startIndex
    let max = range.endIndex
    return Int(arc4random_uniform(UInt32(max - min))) + min
}

斯威夫特 3

这是 Swift 3 的快速更新,作为奖励,它现在适用于任何符合 SignedInteger 协议的值类型 - 对于需要指定 Int16、Int32 等的核心数据应用程序来说更加方便。作为快速说明,如果你真的需要它来处理无符号整数,只需复制整个函数,然后将 SignedInteger 替换为 UnsignedInteger 并将 toIntMax() 替换为 toUIntMax()

func randomNumber<T : SignedInteger>(inRange range: ClosedRange<T> = 1...6) -> T {
    let length = (range.upperBound - range.lowerBound + 1).toIntMax()
    let value = arc4random().toIntMax() % length + range.lowerBound.toIntMax()
    return T(value)
}

斯威夫特 4

由于在 Swift 4 中删除了 toIntMax(),我们现在必须使用不同的方法来转换为常见的整数类型。在此示例中,我使用的 Int64 对我的目的来说足够大,但如果您使用无符号整数或具有 Int128 或 Int256 自定义类型,则应使用它们。

public func randomNumber<T : SignedInteger>(inRange range: ClosedRange<T> = 1...6) -> T {
    let length = Int64(range.upperBound - range.lowerBound + 1)
    let value = Int64(arc4random()) % length + Int64(range.lowerBound)
    return T(value)
}

另外,对于完全随机爱好者,这里有一个扩展,它从任何Collection 类型对象返回一个随机元素。请注意,这使用上述函数来生成其索引,因此您将需要两者。

extension Collection {
    func randomItem() -> Self.Iterator.Element {
        let count = distance(from: startIndex, to: endIndex)
        let roll = randomNumber(inRange: 0...count-1)
        return self[index(startIndex, offsetBy: roll)]
    }
}

用法

randomNumber()

返回 1 到 6 之间的随机数。

randomNumber(50...100)

返回一个介于 50 到 100 之间的数字。当然,您可以将 50 和 100 的值替换为您喜欢的任何值。

斯威夫特 4.2

唉,我最好的 StackOverflow 答案终于过时了。您现在可以简单地使用Int.random(in: 1 ... 6) 来生成给定范围内的随机数。也适用于其他形式的整数和浮点数。集合类型现在还提供shuffle()randomElement() 函数。因此,除非您想使用特定的随机器类型,否则不再需要花哨的随机函数。

【讨论】:

  • 我看了这个并认为它一定是错误的,因为 (max - min) = 5,产生一个 0 到 4 范围内的随机整数(加 1 等于 1 到 5)。但是通过将代码放入 Xcode 游乐场,很明显它是有效的。原因是 max 实际上等于 7,因为 endIndex 返回“集合的第一个‘结束’位置”。 (如 Apple 文档中所述)。所以,对我来说,这是一个很好的答案和有用的学习练习。
  • 这也适用于负整数。只要... 前后有空格,randomNumber(-3 ... -1) 就可以工作。您也可以使用random(-3 ..&lt; -1 排除最后一个数字。
  • 如果您想使用非整数进行这项工作,请使用 ClosedInterval 而不是 Range
  • 我不会。在 Swift 3 中不推荐使用区间类型。可能有一种方法可以使用泛型来扩展代码的功能,但我没有时间、意愿或理由进行调查。
  • 我们开始了,代码的通用整数版本。
【解决方案3】:

如果你想要我为 随机数字创建它。这是数字 Int 和 Double、Float 的扩展

/**
    Arc Random for Double and Float
*/
public func arc4random <T: IntegerLiteralConvertible> (type: T.Type) -> T {
    var r: T = 0
    arc4random_buf(&r, UInt(sizeof(T)))
    return r
}
public extension Int {
    /**
    Create a random num Int
    :param: lower number Int
    :param: upper number Int
    :return: random number Int
    By DaRkDOG
    */
    public static func random (#lower: Int , upper: Int) -> Int {
        return lower + Int(arc4random_uniform(upper - lower + 1))
    }

}
public extension Double {
    /**
    Create a random num Double
    :param: lower number Double
    :param: upper number Double
    :return: random number Double
    By DaRkDOG
    */
    public static func random(#lower: Double, upper: Double) -> Double {
        let r = Double(arc4random(UInt64)) / Double(UInt64.max)
        return (r * (upper - lower)) + lower
    }
}
public extension Float {
    /**
    Create a random num Float
    :param: lower number Float
    :param: upper number Float
    :return: random number Float
    By DaRkDOG
    */
    public static func random(#lower: Float, upper: Float) -> Float {
        let r = Float(arc4random(UInt32)) / Float(UInt32.max)
        return (r * (upper - lower)) + lower
    }
}

使用:

let randomNumDouble = Double.random(lower: 0.00, upper: 23.50)
let randomNumInt = Int.random(lower: 56, upper: 992)
let randomNumInt =Float.random(lower: 6.98, upper: 923.09)

【讨论】:

  • 二元运算符 / 不能应用于两个 Double 操作数
【解决方案4】:

根据 Swift 4.2 现在很容易得到这样的随机数

let randomDouble = Double.random(in: -7.9...12.8)

let randomIntFrom0To10 = Int.random(in: 0 ..< 10)

for more details check this out

【讨论】:

    【解决方案5】:

    我修改了@DaRk-_-D0G 的答案以使用 Swift 2.0

    /**
    Arc Random for Double and Float
    */
    public func arc4random <T: IntegerLiteralConvertible> (type: T.Type) -> T {
        var r: T = 0
        arc4random_buf(&r, sizeof(T))
        return r
    }
    public extension Int {
        /**
        Create a random num Int
        :param: lower number Int
        :param: upper number Int
        :return: random number Int
        By DaRkDOG
        */
        public static func random (lower: Int , upper: Int) -> Int {
            return lower + Int(arc4random_uniform(UInt32(upper - lower + 1)))
        }
    
    }
    public extension Double {
        /**
        Create a random num Double
        :param: lower number Double
        :param: upper number Double
        :return: random number Double
        By DaRkDOG
        */
        public static func random(lower: Double, upper: Double) -> Double {
            let r = Double(arc4random(UInt64)) / Double(UInt64.max)
            return (r * (upper - lower)) + lower
        }
    }
    public extension Float {
        /**
        Create a random num Float
        :param: lower number Float
        :param: upper number Float
        :return: random number Float
        By DaRkDOG
        */
        public static func random(lower: Float, upper: Float) -> Float {
            let r = Float(arc4random(UInt32)) / Float(UInt32.max)
            return (r * (upper - lower)) + lower
        }
    }
    

    【讨论】:

    • 这里是最快的解决方案!非常感谢!
    【解决方案6】:

    从 Swift 4.2 开始:

    Int {    
        public static func random(in range: ClosedRange<Int>) -> Int
        public static func random(in range: Range<Int>) -> Int
    }
    

    像这样使用:

    Int.random(in: 2...10)
    

    【讨论】:

      【解决方案7】:

      编辑:Swift 4.2+ 现在提供了这个:

      (100...200).randomElement()
      

      扩展 Range 对我来说是惯用的:

      public extension Range where Bound == Int {
          var random: Int {
              return lowerBound + Int(arc4random_uniform(UInt32(upperBound - lowerBound)))
          }
      }
      
      public extension ClosedRange where Bound == Int {
          var random: Int {
              return lowerBound + Int(arc4random_uniform(UInt32(upperBound - lowerBound + 1)))
          }
      }
      

      使用中:

      let foo = (100..<600).random
      

      【讨论】:

      • 可能只是一种风格上的东西。这两种方法都没有固有的优势,只是你觉得更舒服。
      • 对于那些认为这种“风格”的人,我有一个语言推荐:C。玩得开心!
      • 我确信有人在 3 年前就已经这样做了 :) stackoverflow.com/questions/34712453/…
      【解决方案8】:

      我做了一个 Int 类型扩展。在操场上进行了测试,希望这很有用。它也接受负范围:

      extension Int
      {
          static func random(range: Range<Int> ) -> Int
          {
              var offset = 0
      
              if range.startIndex < 0   // allow negative ranges
              {
                  offset = abs(range.startIndex)
              }
      
              let mini = UInt32(range.startIndex + offset)
              let maxi = UInt32(range.endIndex   + offset)
      
              return Int(mini + arc4random_uniform(maxi - mini)) - offset
          }
      }
      

      使用喜欢

      var aRandomInt = Int.random(-500...100)  // returns a random number within the given range.
      

      或将其定义为 Range 扩展,如下所示:

      extension Range
      {
          var randomInt: Int
          {
              get
              {
                  var offset = 0
      
                  if (startIndex as Int) < 0   // allow negative ranges
                  {
                      offset = abs(startIndex as Int)
                  }
      
                  let mini = UInt32(startIndex as Int + offset)
                  let maxi = UInt32(endIndex   as Int + offset)
      
                  return Int(mini + arc4random_uniform(maxi - mini)) - offset
              }
          }
      }
      
      // usage example: get an Int within the given Range:
      let nr = (-1000 ... 1100).randomInt
      

      【讨论】:

      • 你的扩展很漂亮:3 Swift 的真正用法!
      • 我喜欢 Range 扩展。
      • 好答案。我唯一需要注意的是,randomInt: 不是 Int 或 Range 的自然扩展。我只需将其作为独立函数添加到实用程序文件中即可。
      • 需要为 swift 3 更新,将 range.startIndex 替换为 range.lowerBound 并且 endIndex 现在是上界
      【解决方案9】:

      斯威夫特 3/4:

      func randomNumber(range: ClosedRange<Int> = 1...6) -> Int {
          let min = range.lowerBound
          let max = range.upperBound
          return Int(arc4random_uniform(UInt32(1 + max - min))) + min
      }
      

      【讨论】:

        【解决方案10】:

        那是因为 arc4random_uniform() 定义如下:

        func arc4random_uniform(_: UInt32) -> UInt32
        

        它需要一个 UInt32 作为输入,然后输出一个 UInt32。您正在尝试向其传递一系列值。 arc4random_uniform 为您提供介于 0 和您传递的数字之间的随机数(仅),因此,例如,如果您想找到一个介于 -50 和 50 之间的随机数,如[-50, 50],您可以使用arc4random_uniform(101) - 50

        【讨论】:

        • Sky 完美回答了我的问题,我相信您也说了同样的话,非常感谢您可以确认通过设置 dice1,2 = arc4random_uniform(6)+1 确实将范围设置为 1- 6 我用断言测试了这个:D
        【解决方案11】:

        答案只有 1 行代码:

        let randomNumber = arc4random_uniform(8999) + 1000 //for 4 digit random number
        let randomNumber = arc4random_uniform(899999999) + 100000000 //for 9 digit random number
        let randomNumber = arc4random_uniform(89) + 10    //for 2 digit random number
        let randomNumber = arc4random_uniform(899) + 100  //for 3 digit random number
        

        替代解决方案是:

            func generateRandomNumber(numDigits: Int) -> Int{
            var place = 1
            var finalNumber = 0;
            var finanum = 0;
            for var i in 0 ..< numDigits {
                place *= 10
                let randomNumber = arc4random_uniform(10)         
                finalNumber += Int(randomNumber) * place
                finanum = finalNumber / 10
                   i += 1
            }
            return finanum
        }
        

        虽然缺点是数字不能从0开始。

        【讨论】:

          【解决方案12】:

          我使用以下代码成功创建了一个随机数:

          var coin = arc4random_uniform(2) + 1
          

          希望对你有帮助。

          【讨论】:

            【解决方案13】:

            迅速...

            这是包容性的,调用 random(1,2) 将返回 1 或 2,这也适用于负数。

                func random(min: Int, _ max: Int) -> Int {
                    guard min < max else {return min}
                    return Int(arc4random_uniform(UInt32(1 + max - min))) + min
                }
            

            【讨论】:

              【解决方案14】:

              斯威夫特:

              var index = 1 + random() % 6
              

              【讨论】:

              • 你需要播种这个,否则你每次都会得到相同的随机数。
              【解决方案15】:

              Swift 3 Xcode Beta 5 解决方案。 基于 Ted van Gaalen 的回答。

              extension Int
                {
                   static func random(range: Range<Int> ) -> Int
                  {
                      var offset = 0
              
                      if range.lowerBound < 0   // allow negative ranges
                      {
                          offset = Swift.abs(range.lowerBound)
                      }
              
                      let mini = UInt32(range.lowerBound + offset)
                      let maxi = UInt32(range.upperBound   + offset)
              
                      return Int(mini + arc4random_uniform(maxi - mini)) - offset
                  }
              }
              

              【讨论】:

                【解决方案16】:

                var rangeFromLimits = arc4random_uniform((UPPerBound - LOWerBound) + 1)) + LOWerBound;

                【讨论】:

                  【解决方案17】:

                  希望这行得通。在 arc4random_uniform() 的范围之间生成随机数?

                  var randomNumber = Int(arc4random_uniform(6))
                  print(randomNumber)
                  

                  【讨论】:

                    【解决方案18】:

                    Ted van Gaalen 使用 Swift 4/Xcode 9+ 回答的Range 扩展的更新版本可能很有用:

                    extension CountableClosedRange where Bound == Int {
                        var randomFromRange: Bound {
                            get {
                                var offset = 0
                                if lowerBound < 0 {
                                    offset = abs(lowerBound)
                                }
                                let mini = UInt32(lowerBound + offset)
                                let maxi = UInt32(upperBound + offset)
                                return Int(mini + arc4random_uniform(maxi - mini)) - offset
                            }
                        }
                    }
                    
                    let n = (-1000 ... 1000).randomFromRange
                    print(n)
                    

                    或者这是一个支持开放和封闭间隔的有点“hacky”的解决方案:

                    extension CountableRange where Bound == Int {
                        var randomFromRange: Bound {
                            return uniformRandom(from: lowerBound, to: upperBound)
                        }
                    }
                    
                    extension CountableClosedRange where Bound == Int {
                        var randomFromRange: Bound {
                            return uniformRandom(from: lowerBound, to: upperBound - 1)
                        }
                    }
                    
                    func uniformRandom(from: Int, to: Int) -> Int {
                        var offset = 0
                        if from < 0 {
                            offset = abs(from)
                        }
                        let mini = UInt32(from + offset)
                        let maxi = UInt32(to + offset)
                        return Int(mini + arc4random_uniform(maxi - mini)) - offset
                    }
                    

                    不确定是否有办法同时为两种类型的间隔添加属性。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2014-03-31
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2017-03-09
                      • 2018-10-20
                      相关资源
                      最近更新 更多