semantic API
semantic 将 floating 的具体值投影到一个与表示无关的小型模型上:精确的既约有理数、带符号的无穷、NaN、由此类标量构成的闭区间,以及一套简短的错误词汇。两个不同表示的值(例如 binary64 的 BinFloat 与 IEEE 的 Decimal)当且仅当表示同一个数时,投影为相等的语义值。本包不执行任何算术运算和舍入。教程 展示了典型的比较;设计页面 推导了该投影为何是精确的以及它会丢弃哪些信息。
示例假定使用以下辅助函数,它将语义标量打印为 numerator/denominator:
///|
fn show(s : @semantic.SemanticScalar) -> String {
match s {
Rational(q) => q.numerator().to_string() + "/" + q.denominator().to_string()
Infinity(@def.Sign::Negative) => "-inf"
Infinity(_) => "+inf"
NaN => "nan"
}
}
精确有理数
ExactRational
ExactRational 是以最简形式保存、分母为正的精确有理数。
pub struct ExactRational {
// private fields
} derive(Eq)
其字段是私有的,因此每个值都由 ExactRational::new 或 ExactRational::from_scaled_integer 构建,并满足不变式
由于每个有理数的这种形式都是唯一的,派生的 == 就是有理数的相等。
ExactRational::new
new(numerator, denominator) 构建有理数 并将其约简。
pub fn ExactRational::new(@bigint.BigInt, @bigint.BigInt) -> Self
负分母的符号会移到分子上;分子分母同除以它们的最大公约数(在 BigInt 上使用欧几里得算法);零变为 。当 denominator 为零时中止。
ExactRational::from_scaled_integer
from_scaled_integer(significand, radix, exponent) 构建精确值 。
pub fn ExactRational::from_scaled_integer(@bigint.BigInt, Int, Int) -> Self
对于 ,结果为 ;对于 ,结果为约简后的 。当 radix 时中止。幂是精确计算的,因此结果的大小随 线性增长(约 位)。
ExactRational::numerator, ExactRational::denominator
这些访问器返回约简后的分子(带符号)和正的分母。
pub fn ExactRational::numerator(Self) -> @bigint.BigInt
pub fn ExactRational::denominator(Self) -> @bigint.BigInt
///|
test "exact rationals are reduced" {
let q = @semantic.ExactRational::new(6N, -8N)
inspect(q.numerator().to_string() + "/" + q.denominator().to_string(), content="-3/4")
let scaled = @semantic.ExactRational::from_scaled_integer(-12N, 10, -3)
inspect(
scaled.numerator().to_string() + "/" + scaled.denominator().to_string(),
content="-3/250",
)
inspect(
@semantic.ExactRational::from_scaled_integer(3N, 2, 4) ==
@semantic.ExactRational::new(48N, 1N),
content="true",
)
}
标量
SemanticScalar
SemanticScalar 表示一个浮点数据的含义。
pub(all) enum SemanticScalar {
Rational(ExactRational)
Infinity(@def.Sign)
NaN
} derive(Eq)
Rational 容纳每个有限值,两种带符号零都表示为 。Infinity 携带 Negative 或 Positive。NaN 代表所有 NaN:静默或信号、任意载荷、任意符号。相等是结构相等,因此这里 NaN == NaN 为 true,与 IEEE 比较不同。
SemanticScalar::from_bin_float
from_bin_float(x) 返回 BinFloat 的精确含义。
pub fn SemanticScalar::from_bin_float(@bin_float.BinFloat) -> Self
有限的 映射为 from_scaled_integer(±c, 2, e) 的 Rational;无穷映射为 Infinity(x.sign());NaN 映射为 NaN。精度被丢弃。从不中止。
SemanticScalar::from_decimal
from_decimal(x) 返回 IEEE @decimal.Decimal 的精确含义。
pub fn SemanticScalar::from_decimal(@decimal.Decimal) -> Self
有限的 映射为 from_scaled_integer(±c, 10, q) 的 Rational,因此同值类的每个成员(1.5、1.50、1.500)都映射为同一个值 。无穷与 NaN 的映射方式与二进制相同。GDA 类型 @decimal_gda.Decimal 在本包中没有投影。
///|
test "project binary and decimal values" {
let binary = @semantic.SemanticScalar::from_bin_float(
@bin_float.BinFloat::from_double(0.1),
)
inspect(show(binary), content="3602879701896397/36028797018963968")
let decimal = @semantic.SemanticScalar::from_decimal(
@decimal.Decimal::from_string("0.1").unwrap(),
)
inspect(show(decimal), content="1/10")
inspect(binary == decimal, content="false")
let half = @semantic.SemanticScalar::from_bin_float(
@bin_float.BinFloat::from_double(0.5),
)
let half_decimal = @semantic.SemanticScalar::from_decimal(
@decimal.Decimal::from_string("0.500").unwrap(),
)
inspect(half == half_decimal, content="true")
inspect(
show(@semantic.SemanticScalar::from_bin_float(@bin_float.BinFloat::from_double(-0.0))),
content="0/1",
)
inspect(
@semantic.SemanticScalar::from_bin_float(@bin_float.BinFloat::nan()) ==
@semantic.SemanticScalar::NaN,
content="true",
)
}
区间
SemanticInterval
SemanticInterval 是由两个语义端点给出的闭区间。
pub struct SemanticInterval {
lower : SemanticScalar
upper : SemanticScalar
} derive(Eq)
其字段是公开的,在包外只读。该类型不检查 lower 是否不超过 upper;下文的投影使用反序对 表示空集。
SemanticInterval::from_ball_float
from_ball_float(x) 投影 BallFloat 的两个端点。
pub fn SemanticInterval::from_ball_float(@ball_float.BallFloat) -> Self
lower 为 from_bin_float(x.lower_bound()),upper 为 from_bin_float(x.upper_bound())。有界区间给出两个 Rational 端点,无界的一侧给出 Infinity,整条实数线给出 ,空区间给出 。装饰、精度和标志均被丢弃。
///|
test "project intervals" {
let x = @semantic.SemanticInterval::from_ball_float(
@ball_float.BallFloat::from_bounds(
@bin_float.BinFloat::from_int(1),
@bin_float.BinFloat::from_double(2.5),
),
)
inspect(show(x.lower) + " .. " + show(x.upper), content="1/1 .. 5/2")
let whole = @semantic.SemanticInterval::from_ball_float(
@ball_float.BallFloat::whole(),
)
inspect(show(whole.lower) + " .. " + show(whole.upper), content="-inf .. +inf")
let empty = @semantic.SemanticInterval::from_ball_float(
@ball_float.BallFloat::empty(),
)
inspect(show(empty.lower) + " .. " + show(empty.upper), content="+inf .. -inf")
}
错误与 checked 结果
SemanticError
SemanticError 是与表示无关的错误词汇。
pub(all) enum SemanticError {
DivisionByZero
ParseError
DomainError
FormatError
UnsupportedOperation
UnorderedComparison
CertificationFailure
} derive(Eq)
它对应 Luna-Flow/arithmetic 的 ArithmeticErrorKind,但不含消息,也不含认证细节。
SemanticError::from_arithmetic
from_arithmetic(err) 对 ArithmeticError 进行分类。
pub fn SemanticError::from_arithmetic(@arithmetic.ArithmeticError) -> Self
种类按以下顺序检测:除以零、解析、定义域、格式、无序比较、认证失败;其他任何情况(UnsupportedOperation 种类)映射为 UnsupportedOperation。消息与 CertificationFailureDetail 被丢弃。
SemanticResult
SemanticResult[T] 是一个语义值或一个语义错误。
pub(all) enum SemanticResult[T] {
Value(T)
Error(SemanticError)
} derive(Eq)
semantic_scalar_result, semantic_interval_result
这些函数将具体包的 checked 结果转换为语义结果,成功情形使用调用者提供的投影。
pub fn[T] semantic_scalar_result(Result[T, @arithmetic.ArithmeticError], (T) -> SemanticScalar) -> SemanticResult[SemanticScalar]
pub fn[T] semantic_interval_result(Result[T, @arithmetic.ArithmeticError], (T) -> SemanticInterval) -> SemanticResult[SemanticInterval]
区间同理。f 至多调用一次。
///|
test "checked results become semantic results" {
let failed = @semantic.semantic_scalar_result(
@bin_float.BinFloat::from_int(1).div_checked(@bin_float.BinFloat::zero()),
@semantic.SemanticScalar::from_bin_float,
)
inspect(
failed == @semantic.SemanticResult::Error(@semantic.SemanticError::DivisionByZero),
content="true",
)
let root = @semantic.semantic_scalar_result(
@bin_float.BinFloat::from_int(4).sqrt(),
@semantic.SemanticScalar::from_bin_float,
)
let two = @semantic.SemanticScalar::from_decimal(@decimal.Decimal::from_int(2))
inspect(root == @semantic.SemanticResult::Value(two), content="true")
}
trait 实现
相等
本包的每个类型都派生 Eq;equal 和 not_equal 方法经显式提升。请优先使用 == 和 !=。
pub fn ExactRational::equal(Self, Self) -> Bool
pub fn ExactRational::not_equal(Self, Self) -> Bool
pub fn SemanticScalar::equal(Self, Self) -> Bool
pub fn SemanticScalar::not_equal(Self, Self) -> Bool
pub fn SemanticInterval::equal(Self, Self) -> Bool
pub fn SemanticInterval::not_equal(Self, Self) -> Bool
pub fn SemanticError::equal(Self, Self) -> Bool
pub fn SemanticError::not_equal(Self, Self) -> Bool
pub fn[T : Eq] SemanticResult::equal(Self[T], Self[T]) -> Bool
pub fn[T : Eq] SemanticResult::not_equal(Self[T], Self[T]) -> Bool
由于采用约简形式,ExactRational 的相等即数值相等;SemanticScalar 的相等额外加入 NaN == NaN,并区分两种无穷。不提供序关系。
完整公共接口
以下快照是该包完整的生成接口。
// Generated using `moon info`, DON'T EDIT IT
package "Luna-Flow/floating/semantic"
import {
"Luna-Flow/arithmetic",
"Luna-Flow/floating/ball_float",
"Luna-Flow/floating/bin_float",
"Luna-Flow/floating/decimal",
"Luna-Flow/floating/def",
"moonbitlang/core/bigint",
}
// Values
pub fn[T] semantic_interval_result(Result[T, @arithmetic.ArithmeticError], (T) -> SemanticInterval) -> SemanticResult[SemanticInterval]
pub fn[T] semantic_scalar_result(Result[T, @arithmetic.ArithmeticError], (T) -> SemanticScalar) -> SemanticResult[SemanticScalar]
// Errors
// Types and methods
pub struct ExactRational {
// private fields
} derive(Eq)
pub fn ExactRational::denominator(Self) -> @bigint.BigInt
pub fn ExactRational::equal(Self, Self) -> Bool
pub fn ExactRational::from_scaled_integer(@bigint.BigInt, Int, Int) -> Self
pub fn ExactRational::new(@bigint.BigInt, @bigint.BigInt) -> Self
pub fn ExactRational::not_equal(Self, Self) -> Bool
pub fn ExactRational::numerator(Self) -> @bigint.BigInt
pub(all) enum SemanticError {
DivisionByZero
ParseError
DomainError
FormatError
UnsupportedOperation
UnorderedComparison
CertificationFailure
} derive(Eq)
pub fn SemanticError::equal(Self, Self) -> Bool
pub fn SemanticError::from_arithmetic(@arithmetic.ArithmeticError) -> Self
pub fn SemanticError::not_equal(Self, Self) -> Bool
pub struct SemanticInterval {
lower : SemanticScalar
upper : SemanticScalar
} derive(Eq)
pub fn SemanticInterval::equal(Self, Self) -> Bool
pub fn SemanticInterval::from_ball_float(@ball_float.BallFloat) -> Self
pub fn SemanticInterval::not_equal(Self, Self) -> Bool
pub(all) enum SemanticResult[T] {
Value(T)
Error(SemanticError)
} derive(Eq)
pub fn[T : Eq] SemanticResult::equal(Self[T], Self[T]) -> Bool
pub fn[T : Eq] SemanticResult::not_equal(Self[T], Self[T]) -> Bool
pub(all) enum SemanticScalar {
Rational(ExactRational)
Infinity(@def.Sign)
NaN
} derive(Eq)
pub fn SemanticScalar::equal(Self, Self) -> Bool
pub fn SemanticScalar::from_bin_float(@bin_float.BinFloat) -> Self
pub fn SemanticScalar::from_decimal(@decimal.Decimal) -> Self
pub fn SemanticScalar::not_equal(Self, Self) -> Bool
// Type aliases
// Traits