【scala原理系列】scala Random原理方法示例源码详解

【scala原理系列】scala Random原理方法示例源码详解

由来原理

Scala中的Random类实际上是对Java中的java.util.Random类的封装。Random类用于生成伪随机数序列。

java.util.Random类是基于线性同余法(linear congruential generator)实现的。该算法使用一个线性递归关系来产生下一个随机数,通过对种子值进行一系列的数学运算得到新的种子值,并返回一个新的伪随机数。

具体而言,java.util.Random类使用了以下公式生成随机数:

seed = (seed * multiplier + addend) & mask

其中seed为当前种子值,multiplieraddend是固定的常数,mask是一个位掩码,用于限制种子值的范围。

在Scala中,Random类提供了与java.util.Random类相似的方法,以便生成各种类型的随机数。它还提供了一些额外的辅助方法,如shuffle()用于对集合进行乱序操作,以及alphanumeric用于生成包含字母数字字符的无限流。

需要注意的是,由于Random类是基于伪随机数生成器实现的,因此生成的随机数序列实际上是可预测的。如果需要更安全的随机数,可以考虑使用SecureRandom类,它提供了更强的随机性和安全性。

方法总结

Random类中的方法归纳为以下几类:

  1. 构造函数:

    • Random(seed: Long)
    • Random(seed: Int)
    • Random()
  2. 生成随机数的方法:

    • nextBoolean(): Boolean
    • nextBytes(bytes: Array[Byte])
    • nextDouble(): Double
    • nextFloat(): Float
    • nextGaussian(): Double
    • nextInt(): Int
    • nextInt(n: Int): Int
    • nextLong(): Long
    • nextString(length: Int): String
    • nextPrintableChar(): Char
  3. 设置种子的方法:

    • setSeed(seed: Long)
  4. 集合操作方法:

    • shuffle[T, CC[X] <: TraversableOnce[X]](xs: CC[T])(implicit bf: CanBuildFrom[CC[T], T, CC[T]]): CC[T]
  5. 辅助方法:

    • alphanumeric: Stream[Char] (返回一个无限流,包含伪随机选择的字母数字字符)

示例

package com.test


import scala.util.Random

object RandomExample {
  def main(args: Array[String]): Unit = {
    val random = new Random()

    // 构造函数
    val random1 = new Random(123)
    val random2 = new Random()

    // 生成随机数的方法
    val randomBoolean = random.nextBoolean()
    val byteArray = new Array[Byte](10)
    random.nextBytes(byteArray)
    val randomDouble = random.nextDouble()
    val randomFloat = random.nextFloat()
    val randomGaussian = random.nextGaussian()
    val randomNumber = random.nextInt()
    val randomRange = random.nextInt(100)
    val randomLong = random.nextLong()
    val randomString = random.nextString(10)
    val randomChar = random.nextPrintableChar()

    // 设置种子的方法
    random.setSeed(123)

    // 集合操作方法
    val list = List(1, 2, 3, 4, 5)
    val shuffledList = random.shuffle(list)

    // 辅助方法
    val alphanumericStream = Random.alphanumeric.take(10)

    println(s"随机布尔值: $randomBoolean")
    println(s"随机字节数组: ${byteArray.mkString(", ")}")
    println(s"随机浮点数: $randomDouble")
    println(s"随机单精度浮点数: $randomFloat")
    println(s"随机高斯分布数: $randomGaussian")
    println(s"随机整数: $randomNumber")
    println(s"指定范围的随机整数 (0-99): $randomRange")
    println(s"随机长整数: $randomLong")
    println(s"随机字符串: $randomString")
    println(s"随机可打印字符: $randomChar")
    println(s"乱序列表: $shuffledList")
    println(s"字母数字字符流: ${alphanumericStream.mkString("")}")
  }

//
//  随机布尔值: true
//  随机字节数组: 35, -36, -41, -91, 83, 38, -32, -111, 12, -70
//  随机浮点数: 0.5518785149199524
//  随机单精度浮点数: 0.93259364
//  随机高斯分布数: 0.3538112818168405
//  随机整数: 719458198
//  指定范围的随机整数 (0-99): 74
//  随机长整数: 3370252708777509741
//  随机字符串: ?患?崡巍?鈬???
//  随机可打印字符: x
//  乱序列表: List(2, 4, 5, 1, 3)
//  字母数字字符流: JTrme7RjeX

}

中文源码分析

package scala
package util

import scala.collection.mutable.ArrayBuffer
import scala.collection.generic.CanBuildFrom
import scala.collection.immutable.{ List, Stream }
import scala.language.{implicitConversions, higherKinds}
/**
 *  Random类是一个随机数生成器,提供了一系列的方法用于生成不同类型的随机数。
 *
 *  @param self 一个java.util.Random对象,用于实现具体的随机数生成逻辑
 */
class Random(val self: java.util.Random) extends AnyRef with Serializable {
  /** 使用一个long类型的种子创建一个新的随机数生成器 */
  def this(seed: Long) = this(new java.util.Random(seed))

  /** 使用一个int类型的种子创建一个新的随机数生成器 */
  def this(seed: Int) = this(seed.toLong)

  /** 创建一个新的随机数生成器 */
  def this() = this(new java.util.Random())

  /** 从该随机数生成器的序列中返回下一个伪随机、均匀分布的boolean值 */
  def nextBoolean(): Boolean = self.nextBoolean()

  /** 生成随机字节并将它们放入用户提供的字节数组中 */
  def nextBytes(bytes: Array[Byte]) { self.nextBytes(bytes) }

  /** 从该随机数生成器的序列中返回下一个伪随机、均匀分布的double值(范围在0.0到1.0之间) */
  def nextDouble(): Double = self.nextDouble()

  /** 从该随机数生成器的序列中返回下一个伪随机、均匀分布的float值(范围在0.0到1.0之间) */
  def nextFloat(): Float = self.nextFloat()

  /** 从该随机数生成器的序列中返回下一个伪随机、高斯(“正态”)分布的double值,均值为0.0,标准差为1.0 */
  def nextGaussian(): Double = self.nextGaussian()

  /** 从该随机数生成器的序列中返回下一个伪随机、均匀分布的int值 */
  def nextInt(): Int = self.nextInt()

  /** 从该随机数生成器的序列中返回一个伪随机、均匀分布的int值,范围在0(包括)到指定值(不包括)之间 */
  def nextInt(n: Int): Int = self.nextInt(n)

  /** 从该随机数生成器的序列中返回下一个伪随机、均匀分布的long值 */
  def nextLong(): Long = self.nextLong()

  /** 返回一个伪随机生成的字符串。该方法并未采取任何措施来保持分布的随机性,
   *  如Unicode的可变长度编码等,因此请勿将其用于重要用途。
   *  主要用于生成测试数据。
   *
   *  @param  length    字符串的长度
   *  @return           生成的字符串
   */
  def nextString(length: Int) = {
    def safeChar() = {
      val surrogateStart: Int = 0xD800
      val res = nextInt(surrogateStart - 1) + 1
      res.toChar
    }

    List.fill(length)(safeChar()).mkString
  }

  /** 返回一个伪随机、均匀分布的ASCII码在33-126之间的字符 */
  def nextPrintableChar(): Char = {
    val low  = 33
    val high = 127
    (self.nextInt(high - low) + low).toChar
  }

  def setSeed(seed: Long) { self.setSeed(seed) }

  /** 返回一个以随机顺序排列的相同类型的新集合。
   *
   *  @return         排列后的集合
   */
  def shuffle[T, CC[X] <: TraversableOnce[X]](xs: CC[T])(implicit bf: CanBuildFrom[CC[T], T, CC[T]]): CC[T] = {
    val buf = new ArrayBuffer[T] ++= xs

    def swap(i1: Int, i2: Int) {
      val tmp = buf(i1)
      buf(i1) = buf(i2)
      buf(i2) = tmp
    }

    for (n <- buf.length to 2 by -1) {
      val k = nextInt(n)
      swap(n - 1, k)
    }

    (bf(xs) ++= buf).result()
  }

  /** 返回一个无限流,其中包含伪随机选择的字母数字字符,
   *  均等地从A-Z、a-z和0-9中选择。
   *
   *  @since 2.8
   */
  def alphanumeric: Stream[Char] = {
    def nextAlphaNum: Char = {
      val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
      chars charAt (self nextInt chars.length)
    }

    Stream continually nextAlphaNum
  }

}

/** Random对象是scala.util.Random的默认实现,提供了一些与随机数相关的便利方法。
 *
 *  @since 2.8
 */
object Random extends Random {

  implicit def javaRandomToRandom(r: java.util.Random): Random = new Random(r)

}
  • 19
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BigDataMLApplication

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值