用Scala实现一个纯函数风格的引用透明的伪随机数生成器

使用Scala生成随机数的方法示例 主要介绍了使用Scala生成随机数的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 立即下载

这个例子来源于scala圣经级教程《Functional Programming in Scala》,由于本人跟着书中的代码敲了一遍,然后写了点测试代码验证了一下正确性,所以就放在这做个备忘吧。贴出来只是为了方便自己,如果看不懂,但是又感兴趣的就去看原书吧……


package state

trait RNG {
  def nextInt: (Int, RNG)
}

object RNG {

  case class Simple(seed: Long) extends RNG {
    override def nextInt: (Int, RNG) = {
      val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
      val nextRNG = Simple(newSeed)
      val n = (newSeed >>> 16).toInt
      (n, nextRNG)
    }
  }

  def nonNegativeInt(rng: RNG): (Int, RNG) = {
    val (i, r) = rng.nextInt
    (if (i < 0) -(i + 1) else i, r)
  }

  /**
    * We generate an integer >= 0 and divide it by one higher than the maximum. This is just one possible solution.
    *
    * @param rng
    * @return
    */
  def double(rng: RNG): (Double, RNG) = {
    val (i, r) = nonNegativeInt(rng)
    (i / Int.MaxValue.toDouble + 1, r)
  }

  def boolean(rng: RNG): (Boolean, RNG) = {

    rng.nextInt match {
      case (i, rng2) => (i % 2 == 0, rng2)
    }
  }

  def intDouble(rng: RNG): ((Int, Double), RNG) = {
    val (i, r1) = rng.nextInt
    val (d, r2) = double(r1)
    ((i, d), r2)
  }

  def doubleInt(rng: RNG): ((Double, Int), RNG) = {
    val ((i, d), r) = intDouble(rng)
    ((d, i), r)
  }

  def double3(rng: RNG): ((Double, Double, Double), RNG) = {
    val (d1, r1) = double(rng)
    val (d2, r2) = double(r1)
    val (d3, r3) = double(r2)
    ((d1, d2, d3), r3)
  }


  // A simple recursive solution
  def ints(count: Int)(rng: RNG): (List[Int], RNG) =
    if (count == 0) (List(), rng) else {
      val (x, r1) = rng.nextInt
      val (xs, r2) = ints(count - 1)(r1)
      (x :: xs, r2)
    }

  // A tail-recursive solution
  def ints2(count: Int)(rng: RNG): (List[Int], RNG) = {
    def go(count: Int, r: RNG, xs: List[Int]): (List[Int], RNG) =
      if (count == 0)
        (xs, r)
      else {
        val (x, r2) = r.nextInt
        go(count - 1, r2, x :: xs)
      }

    go(count, rng, List())
  }

  type Rand[+A] = RNG => (A, RNG)

  /**
    * int是:   val int: Rand[Int] = (rng: RNG) => rng.nextInt 的简写
    */
  val int: Rand[Int] = _.nextInt

  def unit[A](a: A): Rand[A] = rng => (a, rng)

  def map[A, B](s: Rand[A])(f: A => B): Rand[B] = {
    rng => {
      val (a, rng2) = s(rng)
      (f(a), rng2)
    }
  }


  val _double: Rand[Double] = map(nonNegativeInt)(_ / (Int.MaxValue.toDouble + 1))

  def map2[A, B, C](ra: Rand[A], rb: Rand[B])(f: (A, B) => C): Rand[C] = {
    rng => {
      val (a, rng1) = ra(rng)
      val (b, rng2) = rb(rng1)
      (f(a, b), rng2)
    }
  }

  def both[A, B](ra: Rand[A], rb: Rand[B]): Rand[(A, B)] = map2(ra, rb)((_, _))

  val randIntDouble: Rand[(Int, Double)] = both(int, double)

  val randDoubleInt: Rand[(Double, Int)] = both(double, int)

  def sequence[A](fs: List[Rand[A]]): Rand[List[A]] = fs.foldRight(unit(List[A]()))((f, acc) => map2(f, acc)(_ :: _))

  def _ints(n: Int): Rand[List[Int]] = sequence(List.fill(n)(int))


  def flatMap[A, B](f: Rand[A])(g: A => Rand[B]): Rand[B] = rng => {
    val (a, r1) = f(rng)
    g(a)(r1) // pass the new state along
  }


  def nonNegativeLessThan(n: Int): Rand[Int] = {
    flatMap(nonNegativeInt) { i =>
      val mod = i % n
//            print for debug
//      if (i + (n - 1) - mod >= 0) {print(i); print(" "); print(n); print(" "); print(mod); print(" "); unit(mod) } else nonNegativeLessThan(n)
            if (i + (n - 1) - mod >= 0) unit(mod) else nonNegativeLessThan(n)
    }
  }

  def _map[A, B](s: Rand[A])(f: A => B): Rand[B] = flatMap(s)(a => unit(f(a)))


  def _map2[A, B, C](ra: Rand[A], rb: Rand[B])(f: (A, B) => C): Rand[C] = flatMap(ra)(a => map(rb)(b => f(a, b)))


  def main(args: Array[String]): Unit = {

    val now = System.currentTimeMillis();
    val simple = Simple(now)
    println(simple)


    println(simple.nextInt)

    val nonNegativeIntVal = RNG.nonNegativeInt(simple)
    println(nonNegativeIntVal)


    val doubleVal = RNG.double(simple)
    println(doubleVal)

    val booleanVal = RNG.boolean(simple)
    println(booleanVal)

    val intDoubleVal = RNG.intDouble(simple)
    println(intDoubleVal)

    val doubleIntVal = RNG.doubleInt(simple)
    println(doubleIntVal)

    val double3Val = RNG.double3(simple)
    println(double3Val)

    val intsVal = RNG.ints(3)(simple)
    println(intsVal)

    val ints2Val = RNG.ints2(3)(simple)
    println(ints2Val)

    println(RNG.int(simple))

    println(simple)
    println(RNG.unit(100)(simple)._1)
    println(RNG.unit(100)(simple)._2)
    println(RNG.unit(100)(simple)._2.nextInt)


    println(RNG.map(RNG.int)(_ * 2)(simple))


    val _doubleVal = RNG._double(simple)
    println(_doubleVal)


    val map2Val = RNG.map2(RNG.int, RNG.int)((_, _))(simple)
    println(map2Val)


    val bothVal = RNG.both(RNG.int, RNG.int)(simple)
    println(bothVal)


    val intRand5List = List.fill(5)(RNG.int)
    val sequenceVal = RNG.sequence(intRand5List)(simple)
    println(sequenceVal)

    val _intsVal = RNG._ints(5)(simple)
    println(_intsVal)

    val nonNegativeLessThanVal = RNG.nonNegativeLessThan(Int.MaxValue)(simple)
    println(nonNegativeLessThanVal)


  }


}

上述代码的运行结果是:

Simple(1530788766246)
(-697541284,Simple(235760911150649))
(697541283,Simple(235760911150649))
(1.3248179719433273,Simple(235760911150649))
(true,Simple(235760911150649))
((-697541284,1.061915150872392),Simple(8713782830160))
((1.061915150872392,-697541284),Simple(8713782830160))
((1.3248179719433273,1.061915150872392,1.8075593983789717),Simple(167821095294491))
(List(-697541284, 132961774, -1734220603),Simple(167821095294491))
(List(-1734220603, 132961774, -697541284),Simple(167821095294491))
(-697541284,Simple(235760911150649))
Simple(1530788766246)
100
Simple(1530788766246)
(-697541284,Simple(235760911150649))
(-1395082568,Simple(235760911150649))
(0.32481797179207206,Simple(235760911150649))
((-697541284,132961774),Simple(8713782830160))
((-697541284,132961774),Simple(8713782830160))
(List(-697541284, 132961774, -1734220603, 630554181, -192781157),Simple(268840870823373))
(List(-697541284, 132961774, -1734220603, 630554181, -192781157),Simple(268840870823373))
(697541283,Simple(235760911150649))
168、OIS光学防抖系统设计:陀螺仪标定、音圈马达驱动与滚珠式/悬丝式结构选型 本文总结了OIS光学防抖系统设计中的关键问题与解决方案。作者通过实际案例指出,陀螺仪标定需重视零偏、灵敏度和温度补偿问题,音圈马达驱动需采用电流环控制并优化相位补偿。在机械结构选型方面,滚珠式适合大角度补偿但存在回差问题,悬丝式精度高但受重力影响,需根据应用场景选择。系统联调建议从开环到闭环逐步验证,注意陀螺仪与驱动频率匹配。最后给出5条经验建议:关注陀螺仪信噪比而非分辨率、预留标定余量、重视机械结构公差、配备专业调试工具、协调OIS与电子防抖的分工配合。文章强调OIS调试需针对不同模组特性进行反复测试与标 阅读详情

相关推荐

Aveva Marine C# 二次开发入门001

1# 引用 C:\AVEVA\Marine\OH12.1.SP4\Aveva.ApplicationFramework.dll C:\AVEVA\Marine\OH12.1.SP4\Aveva.ApplicationFramework.Presentation.dll 2# 引用命名空间, using Aveva.ApplicationFramework.Presentation;usi...

weixin_30245867的博客 1911

使用Scala生成随机数

一.使用Scala生成随机数 1.简单版本: /* 1.you can use scala.util.Random.nextInt(10) to produce a number between 1 and 10 2.at the same time,you nextInt(100) to produce a number between 1 and 100 */ object Test { ...

说文科技,做有态度的研究。 3万+

K-近邻算法: k-nearest neighbor classification (kNN) 详细介绍

@创建于:2020.04.09 @修改于:2020.04.09,2024.06.22 文章目录1、kNN介绍2、k近邻法的三要素详解2.1 距离度量2.2 k值的选择2.3 分类决策规则3、k近邻法的实现:kd树4、Python实现过程5、优缺点6、常见问题 1、kNN介绍 kNN是一个基本而简单的分类算法,作为监督学习,那么KNN模型需要的是有标签的训练数据,对于新样本的类别由与新样本距离最近的k个训练样本点按照分类...

chenhepg的博客 9万+

scala--生成随机数

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33957648的博客 2204

忍者安全渗透系统(NINJITSU OS V3)的安装详细过程,亲测新旧vm版本都可安装,附带下载来源

忍者安全渗透系统(NINJITSU)的安装详细过程,亲测新旧vm版本都可安装,附带下载来源

1万+

瑞芯微RK3506开发板Ethercat主站性能优化实战:从内核配置到微秒级延迟控制

本文详细介绍了在瑞芯微RK3506开发板上实现EtherCAT主站微秒级延迟控制的实战优化方案。核心在于部署Preempt-RT实时内核,并进行深度系统调优,包括CPU隔离、中断亲和性设置、内存锁定及电源管理调整。通过绕过Linux网络栈的专用驱动加载与配置,最终实现了稳定的高性能实时控制,满足工业自动化需求。

tcp8optimizer的博客 317

函数引用透明性(referential transparency)

函数引用透明性(referential transparency)Scala纯函数

weixin_45101742的博客 387

华为eNSP实战:手把手教你配置DHCP全局地址池(含AP固定IP分配)

本文通过华为eNSP模拟器,详细演示了如何配置DHCP全局地址池,为不同业务VLAN动态分配IP地址,并重点讲解了如何通过MAC地址绑定为接入点(AP)分配固定IP。文章涵盖了从拓扑设计、基础网络搭建到地址池精细配置、验证测试及常见故障排查的全流程,是网络工程师掌握企业级DHCP部署与AP管理的实用指南。

weixin_29235923的博客 600

JavaScript 函数式编程基础概念

函数式编程的一些概念解释: 引用透明(referential transparency)与纯函数、不可变性(Immutability)、等式推理(equational reasoning)、Point-free、惰性求值、柯里化(currying)与偏函数(partial)、compose与pipe。

川上饺子的博客 412

Ubuntu24/Ubuntu22上安装Nvidia显卡驱动最新方案-可解决大多数nvidia-smi不识别和驱动无法加载问题

其实在19年的时候我就写过一篇文章用来安装nvidia显卡驱动的文章,只不过那个时候ubuntu还停留在ubuntu10,时间如梭,一眨眼ubuntu已经升级到ubuntu24了,我写这篇文章是为了给更多的人提供一些在配置nvidia显卡驱动过程中遇到的一些无法用AI,gpt类工具解决的问题。在Ubuntu 24上安装NVIDIA显卡驱动是一项重要的任务,因为它可以提高图形性能并确保系统正常工作。在这篇文章中,我们将介绍如何在Ubuntu 24上安装NVIDIA显卡驱动。

yolo模型训练找我,AI游戏合作找我 3311

YOLOv8【第十章:多任务扩展深度篇·第1节】YOLOv8-Seg 实例分割:Mask原型生成与系数预测原理解析!

🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏。该专栏系统复现并梳理全网各类 YOLOv8 改进与实战案例(当前已覆盖分类 / 检测 / 分割 / 追踪 / 关键点 / OBB 检测等方向),坚持持续更新 + 深度解析,质量分长期稳定在 97 分以上,可视为当前市面上 覆盖较全、更新较快、实战导向极强 的 YOLO 改进系列内容之一。

**My Coding Family** 1816

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

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

wang2leee的博客 1006

具身智能:原理、算法与系统 第18章 模仿学习与人类示范

与基于试错机制的强化学习不同,模仿学习假设存在能够提供高质量轨迹示范的专家策略,学习者的目标是在不直接访问专家内部决策机制的情况下,复现或泛化专家的行为模式。此外,选项 GAIL(Option-GAIL)将分层强化学习与对抗模仿结合,学习选项(Options)级别的策略,能够捕捉专家示范中的多模态行为与高层意图。X-Sim 框架提出从真实到模拟再到真实的迁移路径:首先从人类视频中重建物理仿真环境,在仿真中训练状态级策略,随后通过策略蒸馏获得基于视觉的策略,最后通过在线领域自适应对齐真实与仿真观测。

VectorShift的博客 127

scala,spark生成随机数据测试

sparkSql rdd转DataFrame 随机数据生成

weixin_44947939的博客 1441

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

函数的引用透明性(referential transparency)

1. 基础初学程序设计时,比较容易混淆的两个概念是数学函数(math function)和程序中使用的函数。在数学函数中 y=f(x)y=f(x),一个输入值有固定的输出值。例如,无论计算多少次,sinπ\sin\pi 的结果总是 0。如果 f(x)=x/2f(x)=x/2,那么 f(10)f(10) 无论计算 100 次还是 1000 次,其结果都是 5. 程序设计中的函数却不具备这种稳定的特性,

7706

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

蒯因与引用透明

蒯因又称奎因,美国哲学家,逻辑学家,逻辑实用主义的代表,与罗素齐名,强调系统的、结构式的哲学分析,主张把一般哲学问题置于一个系统的语言框架内进行研究。 蒯因从逻辑的观点出发,把语言分析作为哲学研究的核心内容,这就为哲学的语言转向划上了一个圆满的句号:自蒯因哲学起,当哲学家开始讨论哲学问题的时候,都需要首先考察所要讨论的命题的意义,而不会像传统哲学家那样依然专注于对世界存在的思考。 蒯因

qiruiduni的专栏 2053

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Scala作业7-数据结构(集合)

根据示例数据,输入的字符串集合为 [“Tom”, “Fred”, “Harry”],映射为 {“Tom”->3, “Dick”->4, “Harry”->5}。例如,对于输入的示例数组 [2, -1, 0, 4, -3, 6, -5],生成的新数组将是 [2, 4, 6, -1, 0, -3, -5]。对于输入的示例数组 [1, 2, 3, 4, 5],置换后的结果将是 [2, 1, 4, 3, 5]。函数,它接受一个整数数组作为参数,并生成一个新的数组,其中包含原数组中的所有正值,后跟所有零或负值。

Wzideng@qq.com 1048

scala数组练习

文章目录1.有一个10个位置的数组,第一个位置放的是3,后面每个位置都是前面一个位置的两倍加1,打印这个数组,然后将数组中奇数位置和偶数位置呼唤2.随机10个0到100之间的整数放入数组中,再将数组中的最大值和最小值去掉剩下的数放入新数组,数的顺序不能改变,打印数组3.输入一个整数,将这个整数的所有约束放入一个数组,打印数组 1.有一个10个位置的数组,第一个位置放的是3,后面每个位置都是前面一个位置的两倍加1,打印这个数组,然后将数组中奇数位置和偶数位置呼唤 package com.sunyong //

sun_0128的博客 1万+

Cats(二):引用透明性和等式推理

本文由 Yison 发表在 ScalaCool 团队博客。 上一篇文章 介绍了函数式编程的思维,这一篇我们来了解下函数式编程的魅力。 我们已经说过,函数式编程最关键的事情就是在做「组合」。然而,这种可被组合的「函数式组件」到底是怎样的?换句话说,它们必定符合某些规律和原则。 当前我们已知晓的是,函数式编程是近似于数学中推理的过程。那么我们思考下,数学中的推理具备怎样的特点? 很快,我们便可以发现数...

weixin_34221775的博客 398

当谈论引用透明时,我们在说什么

谈论到引用透明(Referential Transparency),我们都会聊函数式编程(FP),会聊Effect和Side Effect,会聊纯函数(Pure Function)等,这些概念相互关联,有时甚至彼此引用定义,能够真正理解它们的含义非常重要。

IDEAL Garden 492

Scala题目01

Scala题目01

bolinmengling的博客 1046

scala——随机数生成

(new util.Random).nextInt(n) 返回一个0-n(不包括n) 的随机数 比如:scala> (new util.Random).nextInt(3) res7: Int = 1返回一个[0, 2]的随机数scala生成一组不重复的随机数 1、循环获取随机数,再到 list中找,如果没有则添加def randomNew(n:Int)={ var resultList:L

主公在此的博客 6305

scala随机数生成,生成一组不重复随机数算法

scala随机数生成函数 (new util.Random).nextInt(n) 返回一个0-n(不包括n) 的随机数比如scala> (new util.Random).nextInt(3) res7: Int = 1返回一个[0, 2]的随机数 scala生成一组不重复的随机数 1、循环获取随机数,再到 list中找,如果没有则添加 def randomNew(n:Int)=

springlustre的专栏 2万+

scala 在某特定范围内生成随机数

scala随机数生成函数(new util.Random).nextInt(n) 返回一个0-n(不包括n) 的随机数比如scala> (new util.Random).nextInt(3) res7: Int = 1返回一个[0, 2]的随机数scala生成一组不重复的随机数1、循环获取随机数,再到 list中找,如果没有则添加def randomNew(n:Int)={ var res

超级帅的一个小伙子的博客 1万+

Scala 在范围内取得若干不重复的随机数

   此方法依据的是shuffle函数的特性:把数组中的元素按随机顺序重新排序。 import scala.util.Random def main(args: Array[String]): Unit = {   //获得一个0到100的数组 val seq = (0 to 100).map(x=&gt;x) //打乱数组,取得前俩个值 val result = Ran...

Moxice的博客 2219

Scala<产生min-max之间的随机数>

下面的代码是产生1-35范围内的整数 while (true) { var a = 1 + (new Random).nextInt((35 - 1) + 1) if (a <= 0 || a >= 36) print(a) } (new Random).nextInt(n)会产生一个大于等于0且小于n的整数

Gpwner的博客 3881
上一篇: 用Scala实现Stream(一个惰性的链表)数据结构
下一篇: 使用Scala对带状态函数或API进行抽象的示例(State)
lhever_
博客等级 码龄14年 213粉丝 130原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值