第12章 数值类

理解Numeric层次、字面量、算术、Math、转换、位运算、随机与计数,并用明确representation和rounding policy管理近似误差。

学习目标

  • 能解释数值类的构成与数值的字面量在“第12章 数值类”中的责任边界
  • 能围绕“怎样为整数、浮点、随机数与近似比较选择正确数值域和边界?”运行正常与故障轨迹并定位首个分岔
  • 能用“第12章 数值类的输入样本、接收者与方法、关键状态前后值、正常与失败输出、异常或退出状态,以及复位后的再次运行记录。”证明“每个中间值的类型、范围、舍入策略和随机种子都明确。”

来源、版次与运行边界

“第12章 数值类”以作者维护的第 5 版支持页核定 2016 年 3 月 12 日首刷、两位作者、松本行弘监修以及四部分 23 章目录;逐章程序清单练习答案勘误只作为公开支持材料,不被冒充为原书全文。

对“第12章 数值类”而言,中文解释、示例、交互、练习和答案均为独立教学重写;站内中文章名是与官方 23 章顺序对应的课程映射,不宣称是日文小节的逐字翻译,也不从公开程序清单复制整段实现。

“第12章 数值类”固定在 Ruby 2.3 语境;Ruby 2.3.0 官方文档稳定版发布说明用于核对当时可用的语言和标准库行为。现代 Ruby 的差异只能另列迁移说明,不能静默改变本页示例的版本结论。

围绕“怎样为整数、浮点、随机数与近似比较选择正确数值域和边界?”,本页验收“第12章 数值类的输入样本、接收者与方法、关键状态前后值、正常与失败输出、异常或退出状态,以及复位后的再次运行记录。”。先预测正常轨迹,再只注入“先执行整数除法再转为浮点,错误的小数部分已经无法恢复”;若无法定位第一处状态分岔,就拒绝当前解释。

从“数字都是number”这个抽象泄漏开始

Ruby用Numeric层次统一许多operator protocol,但Integer、Float、Rational与Complex表达不同domain。先于选择method。

先预测:5 / 2为何不是2.5?两个Integer执行integer division;改成5.fdiv(2)或让一个operand为Float才得到2.5。Operator surface相同,不代表result domain相同。

数值类的构成

Numeric是抽象superclass,常见subclasses包括Integer、Float、Rational、Complex。Ruby 2.3已统一Fixnum/Bignum行为但class names仍可能可见,现代Ruby合并为Integer;业务代码不要依赖数值大小触发的内部class切换。

Integer提供任意精度语义,memory/time随位数增长;它不会overflow成负数,却可能被恶意超长输入耗尽资源。Float通常基于IEEE 754 double,包含Infinity与NaN等边界。Rational精确保存整数比,Complex保存实部/虚部。

数值的字面量

Integer literal可用十进制、0x十六进制、0b二进制、0o八进制与下划线分组;Float可用decimal point和exponent。不同于运行时String parsing。

p 1_000_000
p 0xff
p 0b1010
p 6.02e23
p Rational(1, 3)
p Complex(2, 3)

External text不要用to_i默认吞掉invalid suffix和返回0;使用Integer(text, 10)Float(text)并处理ArgumentError,再做length/range/domain validation。Leading zero与base自动识别可能引起歧义,协议中固定base。

算术运算

+ - * / % **调用receiver operator methods。Integer /是floor-style integer quotient,div明确整数除法,fdiv明确浮点除法;%/moduloremainder在负数符号上可不同。避免跨语言误迁移。

p 5 / 2
p 5.fdiv(2)
p(-5.div(2))
p(-5 % 2)
p(-5.remainder(2))

ZeroDivisionError对Integer除零抛出;Float除零可能得到Infinity/NaN,取决于operation。检测finite?、nan?并在domain boundary拒绝无效结果。Exponent可能生成巨大Integer或overflow Float,输入指数必须限制。

Math模块

Math提供sqrtsincoslog等module functions,通常返回Float。输入domain错误会抛Math::DomainError或产生特殊值,目标版本需验证。Angle单位通常是radian;API边界明确degree conversion。

Math函数的结果精度受Float限制。Scientific code应记录algorithm、tolerance、conditioning与library/runtime version;业务display rounding不应反向用于中间计算。

数值类型转换

Integer(value)Float(value)执行较严格转换,to_i/to_f往往更宽松。不应混成一个truthy check。

Float转Integer的to_i向0截断;floor向负无穷,ceil向正无穷,round按版本/参数规则取整。金额、分页和坐标各有不同rounding policy,方法名或value object应体现,不要散落.to_i

跨JSON/CSV/database时记录decimal scale、large Integer范围和NaN/Infinity是否可表示。Round-trip test比只测一次parse更能发现precision loss。

位运算

Integer支持& | ^ ~ << >>。Ruby Integer不是固定32/64-bit register,负数位运算可按无限two's-complement直觉表现;与C protocol交互时显式mask width。把抽象Integer映射到协议。

READ = 0b001
WRITE = 0b010
EXECUTE = 0b100
 
permissions = READ | WRITE
p((permissions & WRITE) != 0)
p permissions ^ WRITE
p((~permissions) & 0b111)

Shift count来自输入时限制范围;left shift可产生巨大Integer。Bit flag适合稳定紧凑protocol,但业务可读性需要named constants与encode/decode tests。

随机数

rand使用默认generator;Random.new(seed)创建独立可复现sequence。区分simulation/test与security。

rng = Random.new(12_345)
samples = 5.times.map { rng.rand(1..6) }
p samples

测试注入seeded Random,不修改process-global seed影响其它tests。Token、nonce、password reset使用SecureRandom等CSPRNG,不使用普通rand。统计需求还要验证distribution,不以五个样本证明均匀。

计数

Integer#times、upto、downto和step表达不同sequence;无block时返回Enumerator。避免off-by-one。

1.upto(3)产生1,2,3;3.downto(1)产生3,2,1;1.step(10, 3)产生1,4,7,10。Float step会累积误差,优先按Integer index计算目标值或使用Rational/Decimal domain。

近似值误差

Binary Float无法精确表示多数decimal fraction,因此0.1 + 0.2 == 0.3通常false。不能统一用round掩盖。

actual = 0.1 + 0.2
expected = 0.3
tolerance = 1e-12
 
p actual
p((actual - expected).abs <= tolerance)

Tolerance应结合magnitude使用absolute+relative标准;near zero与大值策略不同。Money使用Integer最小单位或BigDecimal并固定rounding;geometry/physics记录单位和error accumulation。Round只在display、settlement或协议指定boundary执行,避免每步round扩大偏差。

正式节点与章专属证据

  • :第 1 个正式节点要能回到“每个中间值的类型、范围、舍入策略和随机种子都明确。”,并说明故障发生前后的第一处差异。
  • :第 2 个正式节点要能回到“每个中间值的类型、范围、舍入策略和随机种子都明确。”,并说明故障发生前后的第一处差异。
  • :第 3 个正式节点要能回到“每个中间值的类型、范围、舍入策略和随机种子都明确。”,并说明故障发生前后的第一处差异。
  • :第 4 个正式节点要能回到“每个中间值的类型、范围、舍入策略和随机种子都明确。”,并说明故障发生前后的第一处差异。
  • :第 5 个正式节点要能回到“每个中间值的类型、范围、舍入策略和随机种子都明确。”,并说明故障发生前后的第一处差异。
  • :第 6 个正式节点要能回到“每个中间值的类型、范围、舍入策略和随机种子都明确。”,并说明故障发生前后的第一处差异。
  • :第 7 个正式节点要能回到“每个中间值的类型、范围、舍入策略和随机种子都明确。”,并说明故障发生前后的第一处差异。
  • :第 8 个正式节点要能回到“每个中间值的类型、范围、舍入策略和随机种子都明确。”,并说明故障发生前后的第一处差异。
  • :第 9 个正式节点要能回到“每个中间值的类型、范围、舍入策略和随机种子都明确。”,并说明故障发生前后的第一处差异。

对象与状态模型

从输入、接收者到可观察证据

怎样为整数、浮点、随机数与近似比较选择正确数值域和边界?

输入与接收者

固定数值类的构成所需的原始值、Ruby 版本和调用入口。

状态变化

在执行前记录接收者身份,并声明数值的字面量的允许状态。

观察证据

保存第12章 数值类的初值、参数、编码或资源位置。

正式节点:数值类的构成、数值的字面量、算术运算、Math模块、数值类型转换、位运算、随机数、计数、近似值误差

控制与消息轨迹

在相同初值下定位首个分岔

  1. 01固定数值类的构成的输入和接收者
  2. 02执行数值的字面量并记录状态
  3. 03观察算术运算的返回或副作用
  4. 04用近似值误差核对不变量并复位

运行不变量:每个中间值的类型、范围、舍入策略和随机种子都明确。

边界故障探针

一次只破坏一个前提

基线满足:每个中间值的类型、范围、舍入策略和随机种子都明确。

本章回顾:Representation决定可证明的数值语义

  1. Numeric subclasses覆盖不同domain;Integer arbitrary precision不等于无资源上界,Float不提供decimal exactness。
  2. Literal grammar与runtime parsing不同,外部输入按parse、convert、validate三阶段处理。
  3. Division、remainder、Math和bit operations要声明operand type、sign、width与error。
  4. Randomness声明seed/distribution/security,counting声明endpoint/step,便于复现和避免off-by-one。
  5. Approximate comparison依据domain使用tolerance或exact Decimal/Rational,rounding只发生在命名边界。

练习与答案

练习

  1. 问题 1:建立正常轨迹。 回答“怎样为整数、浮点、随机数与近似比较选择正确数值域和边界?”,并写出四步执行记录。
  1. 问题 2:注入单一故障。 只制造“先执行整数除法再转为浮点,错误的小数部分已经无法恢复”,应从哪里开始定位?
  1. 问题 3:覆盖正式节点。 用一个证据包串联数值类的构成、数值的字面量、算术运算、Math模块、数值类型转换、位运算、随机数、计数、近似值误差,说明为什么结论可由另一位读者独立复核。

名词解释

名词解释

本章出现的专业名词,用大白话再讲一遍。

数值类的构成

“第12章 数值类”中的正式节点;必须说明它接收什么、改变什么,以及用什么结果复核。

数值的字面量

“第12章 数值类”中的正式节点;必须说明它接收什么、改变什么,以及用什么结果复核。

算术运算

“第12章 数值类”中的正式节点;必须说明它接收什么、改变什么,以及用什么结果复核。

Math模块

“第12章 数值类”中的正式节点;必须说明它接收什么、改变什么,以及用什么结果复核。

数值类型转换

“第12章 数值类”中的正式节点;必须说明它接收什么、改变什么,以及用什么结果复核。

位运算

“第12章 数值类”中的正式节点;必须说明它接收什么、改变什么,以及用什么结果复核。

随机数

“第12章 数值类”中的正式节点;必须说明它接收什么、改变什么,以及用什么结果复核。

计数

“第12章 数值类”中的正式节点;必须说明它接收什么、改变什么,以及用什么结果复核。

近似值误差

“第12章 数值类”中的正式节点;必须说明它接收什么、改变什么,以及用什么结果复核。

资料与写作方式声明

本章以Ruby 基础教程第 5 版作者支持资料合法公开试读核定可见范围,并以目录限定未公开部分,并结合正文列出的技术资料独立重写;不宣称复现原书正文,也不沿用原作表述。

原作版权归作者与出版社所有;本站原创教学结构与表述仅供学习交流。

讨论

评论区加载中…