我打算通过Swift 3实现一个随机数生成器。我有三种不同的方法可以生成一个整数(0
和50000
之间)一万次不停。
这些生成器是否使用相同的生成值的数学原理?
什么生成器在运行时(具有10000次迭代)的CPU和RAM密集度更低?
方法A :
var generator: Int = random() % 50000
方法B :
let generator = Int(arc4random_uniform(50000))
方法C :
import GameKit
let number: [Int] = [0, 1, 2... 50000]
func generator() -> Int {
let random = GKRandomSource.sharedRandom().nextIntWithUpperBound(number.count)
return number[random]
}
答案 0 :(得分:4)
所有这些都有很好的文档记录,大多数已发布源代码。
var generator: Int = random() % 50000
嗯,首先,这是modulo biased,所以它肯定不等同于适当的统一随机数。 random
的文档解释了它:
random()函数使用非线性,附加反馈,随机数生成器,使用大小为31的长整数的默认表。它返回范围内的连续伪随机数 从0到(2 ** 31)-1。该随机数发生器的周期非常大,约为16 *((2 ** 31)-1)。
但您可以查看Apple source code for libc中的完整实施和文档。
对比arc4random_uniform
的文档(没有模数偏差):
这些函数使用加密伪随机数生成器非常快速地生成高质量的随机字节。一个数据池用于进程中的所有使用者,以便消耗 在程序流程下可以充当额外的搅拌。子系统定期从内核随机数子系统重新播种,也可以在fork(2)上重新播种。
source code也可用。从arc4random_uniform
注意的重要一点是它通过正确调整模数然后生成随机数来避免模偏,直到它在正确的范围内。原则上,这可能需要生成无限数量的随机值;在实践中,非常罕见的是它需要产生不止一个,并且难以置信的难以想象它会产生更多。
GKRandomSource.sharedRandom()
也有详细记录:
系统随机源与arc4random C函数族共享状态。使用此源生成随机数会修改将来对这些函数的调用的结果,并且调用这些函数会修改此源生成的随机值序列。因此,这个来源既不是确定性的,也不是独立的 - 仅用于不依赖于这些属性的琐碎游戏机制。
对于性能,你会期望random()
最快,因为它永远不会从系统熵池中剔除,因此它也不会减少系统中的熵(尽管arc4random
只会这样做周期性地,我相信大约每1.5MB左右产生随机字节;不是每个值都是如此)。但是就像所有的表现一样,你必须要进行描述。当然,由于random()
没有自我重新定位,它的随机性低于arc4random
,/dev/random
本身的随机性低于系统中的熵源(sharedRandom()
)。
如有疑问,如果您有GameplayKit可用,请使用它。 Apple根据他们认为在大多数情况下最有效的方法选择arc4random
的实施。否则使用random
。但是,如果你真的需要尽量减少对系统的影响,那么“非常好”" (但不是加密)随机数,请查看rand
。如果你不太仔细地看待它们,那么你是否愿意随意采取#34;"数字,对系统的影响甚至更小,请查看 # This is the root ITK CMakeLists file.
cmake_minimum_required(VERSION 2.8.9)
if(COMMAND CMAKE_POLICY)
cmake_policy(SET CMP0003 NEW)
endif()
set_target_properties(${TargetName} PROPERTIES COMPILE_FLAGS "/clr")
SET(LINK_LIBRARIES
D:\\2016\\RandomSlicing\\Processing\\lib\\obliquePlane.lib
)
# The header files
SET(HEADERS
ObliquePlaneWrapper.h
obliquePlane.h
)
# The implementation files
SET(SOURCES
ObliquePlaneWrapper.cpp
)
# Find ITK.
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
# Add this as include directory
INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}
${SOURCE_PATH}
${VXL_INCLUDE_DIRS}
)
# Main library
#ADD_EXECUTABLE(obliquePlane ${HEADERS} ${SOURCES})
ADD_LIBRARY(ObliquePlaneWrapper SHARED ${HEADERS} ${SOURCES})
TARGET_LINK_LIBRARIES(ObliquePlaneWrapper ${LINK_LIBRARIES} ${ITK_LIBRARIES})
。如果您希望对系统几乎没有影响(保证O(1),内联),请参阅XKCD's getRandomNumber()。
答案 1 :(得分:1)
Xorshift生成器是最快的非加密安全随机数生成器之一,需要非常小的代码和状态。
快速实现xorshift128 +
的一个例子func xorshift128plus(seed0 : UInt64, seed1 : UInt64) -> () -> UInt64 {
var s0 = seed0
var s1 = seed1
if s0 == 0 && s1 == 0 {
s1 = 1 // The state must be seeded so that it is not everywhere zero.
}
return {
var x = s0
let y = s1
s0 = y
x ^= x << 23
x ^= x >> 17
x ^= y
x ^= y >> 26
s1 = x
return s0 &+ s1
}
}
// create random generator, seed as needed!!
let random = xorshift128plus(seed0: 0, seed1: 0)
for _ in 0..<100 {
// and use it later
random()
}
为了避免模偏,你可以使用
func random_uniform(bound: UInt64)->UInt64 {
var u: UInt64 = 0
let b: UInt64 = (u &- bound) % bound
repeat {
u = random()
} while u < b
return u % bound
}
在你的情况下
let r_number = random_uniform(bound: 5000) // r_number from interval 0..<5000