Files
endorphin-aster-vm/crates/objects/src/number.rs
T

662 lines
26 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 编译器字面量、VM 算术比较与宿主数值转换共用的表示;构造保存与运算预算分开。
//! Eq 比较存储表示,numeric_compare 比较数学值;Rust 数值载荷不持有托管对象边。
//! Lossless number representations. Arithmetic and numeric equivalence are
//! deliberately separate from representation equality; real operations preserve
//! exact values unless a binary-float operand explicitly selects float mode.
use std::any::Any;
use std::fmt;
use crate::{CompareOp, ObjectPayload, ObjectRef, VmError};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EndorInteger {
/// 规范化整数符号,零为 false。
negative: bool,
/// 无符号、无前导零的数字串;零保留单个 0。
digits: String,
}
impl EndorInteger {
/// Decimal digits of any length, limited only by available memory.
/// 编译器/宿主解析字面量,构造可保留长数字,实际算术再执行预算检查。
pub fn parse(text: &str) -> Result<Self, VmError> {
// 拆符号后校验数字,空串或只有符号均非法。
let (negative, digits) = split_sign(text);
// 只允许非空 ASCII 数字,不接受空白、下划线或进制前缀。
if !is_digits(digits) {
return Err(VmError::InvalidArgument("invalid integer"));
}
// 去前导零,全零统一保存单个正零。
let digits = digits.trim_start_matches('0');
Ok(Self {
negative: negative && !digits.is_empty(),
digits: if digits.is_empty() { "0" } else { digits }.into(),
})
}
/// 宿主/转换借用规范化整数绝对值数字串。
pub fn digits(&self) -> &str {
&self.digits
}
/// 查询整数符号,构造已消除负零。
pub fn is_negative(&self) -> bool {
self.negative
}
/// 数值真值/分母检查使用的零判断,具体实现按表示处理。
pub fn is_zero(&self) -> bool {
self.digits == "0"
}
/// 算术快路径尝试收窄整数,超范围返回 None,不截断。
pub fn to_i64(&self) -> Option<i64> {
// 先读 u64 幅值以容纳 i64::MIN 的绝对值,再检查有符号范围。
let magnitude = self.digits.parse::<u64>().ok()?;
if self.negative {
// 最小负数的幅值比最大正数多一,必须单独处理。
if magnitude == (i64::MAX as u64) + 1 {
Some(i64::MIN)
} else {
i64::try_from(magnitude).ok()?.checked_neg()
}
} else {
i64::try_from(magnitude).ok()
}
}
}
impl fmt::Display for EndorInteger {
/// Display/宿主诊断按当前表示输出,精确表示不经二进制浮点中转。
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.negative {
f.write_str("-")?;
}
f.write_str(&self.digits)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EndorDecimal {
/// 已验证但未规范化的原十进制字面量。
literal: String,
/// 缓存尾数是否全零。
zero: bool,
}
impl EndorDecimal {
/// Retains all digits, trailing zeroes, sign, and an arbitrarily long
/// decimal exponent. No intermediate binary floating-point conversion.
/// 编译器/宿主解析字面量,构造可保留长数字,实际算术再执行预算检查。
pub fn parse(text: &str) -> Result<Self, VmError> {
// 校验时去符号,但最终仍保存完整 text,不丢失显式正号和负零。
let (_, unsigned) = split_sign(text);
// 指数最多一段,可带符号;解析不立刻收窄指数到机器整数。
let mut parts = unsigned.split(['e', 'E']);
// 尾数后续允许一个点和至少一个数字。
let mantissa = parts.next().unwrap_or_default();
// 指数必须有数字且不得有第二个指数段。
if let Some(exponent) = parts.next()
&& (!is_digits(split_sign(exponent).1) || parts.next().is_some())
{
return Err(VmError::InvalidArgument("invalid decimal exponent"));
}
// 分别记录已有小数点、数字数量与尾数是否全零。
let mut decimal_point = false;
let mut digits = 0_usize;
let mut zero = true;
// 按 ASCII 字节扫描,第二个点或其他字符都拒绝。
for byte in mantissa.bytes() {
match byte {
b'.' if !decimal_point => decimal_point = true,
b'0'..=b'9' => {
digits += 1;
zero &= byte == b'0';
}
_ => return Err(VmError::InvalidArgument("invalid decimal")),
}
}
// 允许 .5 和 5.,但不允许只有点或空尾数。
if digits == 0 {
return Err(VmError::InvalidArgument("decimal needs digits"));
}
Ok(Self {
literal: text.into(),
zero,
})
}
/// 显示和精确转换借用原字面量,保留符号、指数及尾零。
pub fn literal(&self) -> &str {
&self.literal
}
/// 数值真值/分母检查使用的零判断,具体实现按表示处理。
pub fn is_zero(&self) -> bool {
self.zero
}
}
impl fmt::Display for EndorDecimal {
/// Display/宿主诊断按当前表示输出,精确表示不经二进制浮点中转。
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.literal)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EndorRational {
/// 带符号分子,不要求已约分。
numerator: EndorInteger,
/// 构造保证正且非零的分母。
denominator: EndorInteger,
}
impl EndorRational {
/// Normalizes denominator sign, without reducing or rounding the fraction.
/// 宿主/Store 构造当前数值表示或载荷,具体不变量见下方构造步骤。
pub fn new(
mut numerator: EndorInteger,
mut denominator: EndorInteger,
) -> Result<Self, VmError> {
// 构造时拒绝零分母,后续零判断只需看分子。
if denominator.is_zero() {
return Err(VmError::InvalidArgument("zero rational denominator"));
}
// 分母归正,同时翻分子符号;不执行约分。
if denominator.negative {
denominator.negative = false;
// 零分子保持正零,不引入负零。
if !numerator.is_zero() {
numerator.negative = !numerator.negative;
}
}
Ok(Self {
numerator,
denominator,
})
}
/// 显示与精确转换借用分子表示。
pub fn numerator(&self) -> &EndorInteger {
&self.numerator
}
/// 显示与精确转换借用正且非零的分母表示。
pub fn denominator(&self) -> &EndorInteger {
&self.denominator
}
}
impl fmt::Display for EndorRational {
/// Display/宿主诊断按当前表示输出,精确表示不经二进制浮点中转。
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}/{}", self.numerator, self.denominator)
}
}
/// Internal storage forms within one Endor number API, not language classes.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EndorReal {
Integer(EndorInteger),
Decimal(EndorDecimal),
Rational(EndorRational),
/// IEEE-754 bits preserve signed zero, infinities and NaN payloads.
BinaryFloat(u64),
}
impl EndorReal {
/// 数值真值/分母检查使用的零判断,具体实现按表示处理。
pub fn is_zero(&self) -> bool {
match self {
Self::Integer(value) => value.is_zero(),
Self::Decimal(value) => value.is_zero(),
Self::Rational(value) => value.numerator.is_zero(),
Self::BinaryFloat(bits) => f64::from_bits(*bits) == 0.0,
}
}
}
impl fmt::Display for EndorReal {
/// Display/宿主诊断按当前表示输出,精确表示不经二进制浮点中转。
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Integer(value) => value.fmt(f),
Self::Decimal(value) => value.fmt(f),
Self::Rational(value) => value.fmt(f),
Self::BinaryFloat(bits) => f64::from_bits(*bits).fmt(f),
}
}
}
/// Unified, lossless number value. PartialEq/Eq compare representations, NOT
/// mathematical values: decimal scale and IEEE NaN bits remain observable.
/// Language-level comparison and hashing are not defined by these Rust traits.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EndorNumber {
Real(EndorReal),
Complex {
/// 复数实部分量。
real: EndorReal,
/// 复数虚部分量。
imaginary: EndorReal,
},
}
impl EndorNumber {
/// 编译器/宿主构造整数实数表示,解析错误原样传播。
pub fn integer(text: &str) -> Result<Self, VmError> {
Ok(Self::Real(EndorReal::Integer(EndorInteger::parse(text)?)))
}
/// 编译器/宿主构造保留字面量的十进制实数。
pub fn decimal(text: &str) -> Result<Self, VmError> {
Ok(Self::Real(EndorReal::Decimal(EndorDecimal::parse(text)?)))
}
/// 宿主/运算结果从两段整数文本建立有理数,拒绝零分母。
pub fn rational(numerator: &str, denominator: &str) -> Result<Self, VmError> {
Ok(Self::Real(EndorReal::Rational(EndorRational::new(
EndorInteger::parse(numerator)?,
EndorInteger::parse(denominator)?,
)?)))
}
/// 宿主显式选择二进制浮点,保存全部 IEEE 位。
pub fn binary_float(value: f64) -> Self {
Self::Real(EndorReal::BinaryFloat(value.to_bits()))
}
/// 组合两分量,不因虚部为零自动退化为实数;当前不支持复数算术。
pub fn complex(real: EndorReal, imaginary: EndorReal) -> Self {
Self::Complex { real, imaginary }
}
/// VM 算术/转换查询实数,Complex 即使虚部为零也返回 None。
pub fn as_real(&self) -> Option<&EndorReal> {
match self {
Self::Real(value) => Some(value),
Self::Complex { .. } => None,
}
}
/// VM 快路径仅接受整数变体,不自动转小数或可整除分数。
pub fn as_i64(&self) -> Option<i64> {
match self {
Self::Real(EndorReal::Integer(value)) => value.to_i64(),
_ => None,
}
}
/// 数值真值/分母检查使用的零判断,具体实现按表示处理。
pub fn is_zero(&self) -> bool {
match self {
Self::Real(value) => value.is_zero(),
Self::Complex { real, imaginary } => real.is_zero() && imaginary.is_zero(),
}
}
}
impl From<i64> for EndorNumber {
/// Rust 宿主转换入口,按输入类型选择整数文本或显式二进制浮点表示。
fn from(value: i64) -> Self {
Self::integer(&value.to_string()).expect("i64 always has valid decimal digits")
}
}
impl From<f64> for EndorNumber {
/// Rust 宿主转换入口,按输入类型选择整数文本或显式二进制浮点表示。
fn from(value: f64) -> Self {
Self::binary_float(value)
}
}
impl fmt::Display for EndorNumber {
/// Display/宿主诊断按当前表示输出,精确表示不经二进制浮点中转。
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Real(value) => value.fmt(f),
Self::Complex { real, imaginary } => write!(f, "({real} + ({imaginary})i)"),
}
}
}
#[derive(Debug, Clone)]
pub struct EndorNumberObject {
/// 拥有数值表示,不含托管对象强边。
value: EndorNumber,
}
impl EndorNumberObject {
/// 宿主/Store 构造当前数值表示或载荷,具体不变量见下方构造步骤。
pub fn new(value: EndorNumber) -> Self {
Self { value }
}
/// VM/宿主借用堆数值,不增加根或复制内容。
pub fn value(&self) -> &EndorNumber {
&self.value
}
}
impl ObjectPayload for EndorNumberObject {
/// 数值载荷不可变,不实现旧式原地赋值,允许只读局部重绑定。
fn reference_assignment_only(&self) -> bool {
true
}
/// Store 的 Rust 载荷下转型入口。
fn as_any(&self) -> &dyn Any {
self
}
/// Store 错误与诊断使用的载荷类别,不是名义类型。
fn kind_name(&self) -> &'static str {
"number"
}
/// Store 显示数值,不打印对象地址。
fn repr(&self, _identity: ObjectRef) -> Result<String, VmError> {
Ok(self.value.to_string())
}
/// Store 真值协议按非零判断,复数要求两分量都为零才为假。
fn is_true(&self) -> Result<bool, VmError> {
Ok(!self.value.is_zero())
}
/// 统一数值哈希尚未定义,拒绝以免数学相等而表示不同的键哈希不兼容。
fn hash(&self, _identity: ObjectRef) -> Result<u64, VmError> {
Err(VmError::UnsupportedOperation("numeric hash"))
}
/// Store 对象比较协议,只在对方也是数值载荷时处理,否则返回 None。
fn compare(&self, other: &dyn ObjectPayload, op: CompareOp) -> Result<Option<bool>, VmError> {
// 异类载荷不强行比较,交给 Store 的反向协议或身份回退。
if let Some(other) = other.as_any().downcast_ref::<Self>() {
// 复数目前连相等比较也不支持,明确报协议错误。
if self.value.as_real().is_none() || other.value.as_real().is_none() {
return Err(VmError::UnsupportedOperation("numeric comparison"));
}
return self.value.numeric_compare(&other.value, op).map(Some);
}
Ok(None)
}
}
/// 解析共用单个符号拆分,不去空白或重复符号。
fn split_sign(text: &str) -> (bool, &str) {
// 只剥离一个前导符号,剩余文本交给数字语法校验。
if let Some(rest) = text.strip_prefix('-') {
(true, rest)
} else {
(false, text.strip_prefix('+').unwrap_or(text))
}
}
/// 解析共用非空 ASCII 数字检查,不接受 Unicode 数字。
fn is_digits(text: &str) -> bool {
!text.is_empty() && text.bytes().all(|byte| byte.is_ascii_digit())
}
/// Source arithmetic is exact for integers/decimals/rationals. A binary-float
/// operand explicitly selects IEEE floating-point arithmetic, as used by host
/// geometry/math APIs. Complex arithmetic remains unsupported.
#[derive(Debug, Clone, Copy)]
pub enum ArithmeticOp {
Add,
Subtract,
Multiply,
Divide,
}
impl ArithmeticOp {
/// eval 解 BinaryArithmetic 的 0..3 运算编号,其他值返回 None。
pub fn from_argument(value: u32) -> Option<Self> {
match value {
0 => Some(Self::Add),
1 => Some(Self::Subtract),
2 => Some(Self::Multiply),
3 => Some(Self::Divide),
_ => None,
}
}
}
impl EndorNumber {
/// eval 一元负号:浮点翻符号位,其余走零减当前值,因此仍受运算预算限制。
pub fn negated(&self) -> Result<Self, VmError> {
// 翻转符号位保留负零和 NaN payload,不经算术规范化。
if let Some(EndorReal::BinaryFloat(bits)) = self.as_real() {
return Ok(Self::Real(EndorReal::BinaryFloat(bits ^ (1_u64 << 63))));
}
Self::from(0_i64).arithmetic(self, ArithmeticOp::Subtract)
}
/// Explicit narrowing for graphics/FFI boundaries; exact values themselves
/// retain their representation. Non-real or non-finite values are rejected.
/// 宿主图形/FFI 显式收窄,拒绝复数、非有限值和不可转换范围。
pub fn to_f64(&self) -> Result<f64, VmError> {
use num_traits::ToPrimitive;
// 先要求 Real,不能静默丢弃复数虚部。
let real = self
.as_real()
.ok_or(VmError::UnsupportedOperation("complex to float"))?;
// 浮点还原原位,精确表示先转 BigRational 再收窄。
let value = if let EndorReal::BinaryFloat(bits) = real {
f64::from_bits(*bits)
} else {
exact_real(real)?.to_f64().ok_or(VmError::InvalidArgument(
"number exceeds binary float range",
))?
};
// 图形/FFI 边界不接受 NaN 或无穷。
if !value.is_finite() {
return Err(VmError::InvalidArgument("non-finite float conversion"));
}
Ok(value)
}
/// eval 二元算术:i64 安全快路径,任一浮点选择 float,否则精确有理数运算。
pub fn arithmetic(&self, other: &Self, op: ArithmeticOp) -> Result<Self, VmError> {
// 双方为可容纳 i64 的 Integer 才用快路径;运算溢出回退,不截断。
if let (Some(a), Some(b)) = (self.as_i64(), other.as_i64()) {
// 加减乘检查溢出,除法仅整除且不溢出时保持整数快路径。
let integer = match op {
ArithmeticOp::Add => a.checked_add(b),
ArithmeticOp::Subtract => a.checked_sub(b),
ArithmeticOp::Multiply => a.checked_mul(b),
ArithmeticOp::Divide => a
.checked_rem(b)
.filter(|&r| r == 0)
.and_then(|_| a.checked_div(b)),
};
// 快路径成功后包装为规范化整数。
if let Some(result) = integer {
return Ok(Self::from(result));
}
}
use num_traits::{ToPrimitive, Zero};
// 先要求两个输入均为实数;后续按精确/浮点模式转换。
let (a, b) = (
self.as_real()
.ok_or(VmError::UnsupportedOperation("complex arithmetic"))?,
other
.as_real()
.ok_or(VmError::UnsupportedOperation("complex arithmetic"))?,
);
// 显式浮点参与才启用 float,精确十进制本身不自动选 float。
if matches!(a, EndorReal::BinaryFloat(_)) || matches!(b, EndorReal::BinaryFloat(_)) {
// 混合算术中精确侧可收窄,浮点侧还原原位。
let convert = |n: &EndorReal| -> Result<f64, VmError> {
// 已为 float 则还原,否则精确转换后检查能否收窄。
if let EndorReal::BinaryFloat(bits) = n {
Ok(f64::from_bits(*bits))
} else {
exact_real(n)?.to_f64().ok_or(VmError::InvalidArgument(
"number exceeds binary float range",
))
}
};
// 先要求两个输入均为实数;后续按精确/浮点模式转换。
let (a, b) = (convert(a)?, convert(b)?);
// 两种运算模式都拒绝零除,包括浮点正负零。
if matches!(op, ArithmeticOp::Divide) && b == 0. {
return Err(VmError::InvalidArgument("division by zero"));
}
// 执行指定运算;浮点后检查有限性,精确后检查结果预算。
let result = match op {
ArithmeticOp::Add => a + b,
ArithmeticOp::Subtract => a - b,
ArithmeticOp::Multiply => a * b,
ArithmeticOp::Divide => a / b,
};
// 拒绝 NaN 传播或溢出为无穷,不返回非有限算术结果。
if !result.is_finite() {
return Err(VmError::InvalidArgument("non-finite arithmetic result"));
}
return Ok(Self::binary_float(result));
}
// 先要求两个输入均为实数;后续按精确/浮点模式转换。
let (a, b) = (exact_real(a)?, exact_real(b)?);
// 两种运算模式都拒绝零除,包括浮点正负零。
if matches!(op, ArithmeticOp::Divide) && b.is_zero() {
return Err(VmError::InvalidArgument("division by zero"));
}
// 执行指定运算;浮点后检查有限性,精确后检查结果预算。
let result = match op {
ArithmeticOp::Add => a + b,
ArithmeticOp::Subtract => a - b,
ArithmeticOp::Multiply => a * b,
ArithmeticOp::Divide => a / b,
};
// 限制运算后分子/分母位数,构造保存上限与实际运算预算不同。
if result.numer().bits() > 16_384 || result.denom().bits() > 16_384 {
return Err(VmError::InvalidArgument(
"arithmetic result exceeds operation budget",
));
}
// 可整除输出 Integer,否则输出约分后 Rational,不伪造 Decimal 小数位。
if result.is_integer() {
Self::integer(&result.to_integer().to_string())
} else {
Self::rational(&result.numer().to_string(), &result.denom().to_string())
}
}
/// eval/数值载荷数学比较,拒绝复数,处理 NaN 无序与无穷,不依赖 Rust Eq。
pub fn numeric_compare(&self, other: &Self, op: CompareOp) -> Result<bool, VmError> {
use std::cmp::Ordering;
// 先要求两个输入均为实数;后续按精确/浮点模式转换。
let (a, b) = (
self.as_real()
.ok_or(VmError::UnsupportedOperation("complex comparison"))?,
other
.as_real()
.ok_or(VmError::UnsupportedOperation("complex comparison"))?,
);
// 双方均为可容纳 i64 的 Integer 时直接比较,不需要大整数分配。
if let (Some(a), Some(b)) = (self.as_i64(), other.as_i64()) {
return Ok(match op {
CompareOp::Eq => a == b,
CompareOp::Ne => a != b,
CompareOp::Lt => a < b,
CompareOp::Le => a <= b,
CompareOp::Gt => a > b,
CompareOp::Ge => a >= b,
});
}
// Finite binary floats compare as exact binary rationals, so a large
// integer never loses precision merely to answer an ordering question.
// 双浮点使用 partial_cmp;有限混合比较转精确分数,避免大整数失真。
let order = if let (EndorReal::BinaryFloat(a), EndorReal::BinaryFloat(b)) = (a, b) {
f64::from_bits(*a).partial_cmp(&f64::from_bits(*b))
} else {
// 识别混合比较中的浮点 NaN/无穷,其他表示只有有限值。
let nonfinite = |n: &EndorReal| match n {
EndorReal::BinaryFloat(bits) if !f64::from_bits(*bits).is_finite() => {
Some(f64::from_bits(*bits))
}
_ => None,
};
// NaN 无序,无穷按符号超出有限值,其他输入走精确比较。
match (nonfinite(a), nonfinite(b)) {
(Some(a), _) if a.is_nan() => None,
(_, Some(b)) if b.is_nan() => None,
(Some(a), _) => Some(if a.is_sign_positive() {
Ordering::Greater
} else {
Ordering::Less
}),
(_, Some(b)) => Some(if b.is_sign_positive() {
Ordering::Less
} else {
Ordering::Greater
}),
_ => Some(exact_real(a)?.cmp(&exact_real(b)?)),
}
};
// 无序令 Eq 和有序关系为 false,Ne 为 true。
Ok(match op {
CompareOp::Eq => order == Some(Ordering::Equal),
CompareOp::Ne => order != Some(Ordering::Equal),
CompareOp::Lt => order == Some(Ordering::Less),
CompareOp::Le => matches!(order, Some(Ordering::Less | Ordering::Equal)),
CompareOp::Gt => order == Some(Ordering::Greater),
CompareOp::Ge => matches!(order, Some(Ordering::Greater | Ordering::Equal)),
})
}
}
/// 算术/比较/收窄共用精确有理数转换,有限浮点按精确二进制分数处理,有操作预算。
fn exact_real(value: &EndorReal) -> Result<num_rational::BigRational, VmError> {
use num_bigint::BigInt;
use num_rational::BigRational;
// 大整数转换先限制文本长度,含可能的符号。
let integer = |s: &str| -> Result<BigInt, VmError> {
// 超预算报错,不以截断或浮点近似继续。
if s.len() > 4096 {
return Err(VmError::InvalidArgument(
"numeric operand exceeds operation budget",
));
}
s.parse()
.map_err(|_| VmError::InvalidArgument("invalid exact number"))
};
match value {
EndorReal::Integer(n) => Ok(BigRational::from_integer(integer(&n.to_string())?)),
EndorReal::Rational(n) => Ok(BigRational::new(
integer(&n.numerator.to_string())?,
integer(&n.denominator.to_string())?,
)),
EndorReal::BinaryFloat(bits) => BigRational::from_float(f64::from_bits(*bits))
.ok_or(VmError::InvalidArgument("non-finite exact conversion")),
EndorReal::Decimal(n) => {
// 十进制已通过构造语法检查,这里为运算解析指数。
let parts: Vec<_> = n.literal.split(['e', 'E']).collect();
// 保存允许很长指数,实际运算要求可转为 i32。
let exponent = if parts.len() == 2 {
parts[1].parse::<i32>().map_err(|_| {
VmError::InvalidArgument("numeric exponent exceeds operation budget")
})?
} else {
0
};
// 尾数的小数位数须从指数扣除,确定整体十进制缩放。
let decimals = parts[0].split_once('.').map_or(0, |(_, s)| s.len()) as i64;
// 提升到 i64 计算指数差,随后检查绝对幂次预算。
let power = i64::from(exponent) - decimals;
// 限制生成巨大十次幂的工作量,不只限制结果显示长度。
if power.abs() > 4096 {
return Err(VmError::InvalidArgument(
"numeric exponent exceeds operation budget",
));
}
// 去掉小数点但保留符号,将尾数转为整数。
let digits = integer(&parts[0].replace('.', ""))?;
// 预算通过才计算精确的 10 次幂,不调用浮点 pow。
let factor = BigInt::from(10).pow(power.unsigned_abs() as u32);
// 负幂放分母,非负幂乘分子;BigRational 规范化结果。
Ok(if power < 0 {
BigRational::new(digits, factor)
} else {
BigRational::from_integer(digits * factor)
})
}
}
}