【PhysUnits】15.17 比例因子模块 (ratio.rs) - 实践
一、源码
这个模块定义了一个用于表示比例因子的类型系统,通过质因数分解的方式来表示各种比例关系,特别适用于处理非10的幂次的比例(如时间单位、角度单位等)。
// ratio.rs
//! 比例因子模块,处理所有非10的幂次的比例关系,包括时间单位、角度单位等
use crate::sealed::Sealed;
use crate::constant::{
Z0, Integer, Sum, Diff
};
use core::marker::PhantomData;
use core::ops::{
Add, Sub, Mul, Div
};
// use core::f64::consts::PI;
/// 比例因子结构体,使用质因数分解表示
/// Exp5: 5的幂次
/// Exp3: 3的幂次
/// ExpPi: PI的幂次
/// Exp2: 2的幂次
#[derive(Debug, Clone, Copy, Default)]
pub struct Ratio<
Exp5: Integer, ExpPi:Integer, Exp3: Integer, Exp2: Integer>
(
PhantomData<
(Exp5, ExpPi, Exp3, Exp2)>
);
/* impl<E5: Integer, Pi: Integer, E3: Integer, E2: Integer> Ratio<E5, Pi, E3, E2>{
/// 计算比例因子的实际值
pub fn value() -> f64 {
5f64.powi(E5::to_i32()) * PI.powi(Pi::to_i32()) * 3f64.powi(E3::to_i32()) * 2f64.powi(E2::to_i32())
}
/* /// 获取比例因子的符号表示
pub fn symbol() -> &'static str {
// 检查是否是时间单位
if let Some(sym) = Self::time_symbol() {
return sym;
}
} */
} */
// 实现比例因子的乘法
impl<
E5a, EPia, E3a, E2a, E5b, EPib, E3b, E2b>
Mul<
Ratio<
E5b, EPib, E3b, E2b>>
for Ratio<
E5a, EPia, E3a, E2a>
where
E5a: Integer + Add<
E5b, Output: Integer>
,
EPia: Integer + Add<
EPib, Output: Integer>
,
E3a: Integer + Add<
E3b, Output: Integer>
,
E2a: Integer + Add<
E2b, Output: Integer>
,
E5b: Integer,
EPib: Integer,
E3b: Integer,
E2b: Integer,
{
type Output = Ratio<
Sum<
E5a, E5b>
, Sum<
EPia, EPib>
, Sum<
E3a, E3b>
, Sum<
E2a, E2b>>
;
fn mul(self, _: Ratio<
E5b, EPib, E3b, E2b>
) ->
Self::Output {
Ratio(PhantomData)
}
}
// 实现比例因子的除法
impl<
E5a, EPia, E3a, E2a, E5b, EPib, E3b, E2b>
Div<
Ratio<
E5b, EPib, E3b, E2b>>
for Ratio<
E5a, EPia, E3a, E2a>
where
E5a: Integer + Sub<
E5b, Output: Integer>
,
EPia: Integer + Sub<
EPib, Output: Integer>
,
E3a: Integer + Sub<
E3b, Output: Integer>
,
E2a: Integer + Sub<
E2b, Output: Integer>
,
E5b: Integer,
EPib: Integer,
E3b: Integer,
E2b: Integer,
{
type Output = Ratio<
Diff<
E5a, E5b>
, Diff<
EPia, EPib>
, Diff<
E3a, E3b>
, Diff<
E2a, E2b>>
;
fn div(self, _: Ratio<
E5b, EPib, E3b, E2b>
) ->
Self::Output {
Ratio(PhantomData)
}
}
pub trait Scaled: Sealed{
}
impl<
Exp5: Integer, ExpPi:Integer, Exp3: Integer, Exp2: Integer>
Sealed for Ratio<
Exp5, ExpPi, Exp3, Exp2>
{
}
impl<
Exp5: Integer, ExpPi:Integer, Exp3: Integer, Exp2: Integer>
Scaled for Ratio<
Exp5, ExpPi, Exp3, Exp2>
{
}
// ========== 常用比例定义 ==========
/// 单位1 (无比例)
pub type RatioOne = Ratio<
Z0, Z0, Z0, Z0>
;
// ========== 实用类型别名 ==========
/// 计算两个比例的乘积类型
pub type RatioMul<
A, B>
= <
A as Mul<
B>>
::Output;
/// 计算两个比例的商类型
pub type RatioDiv<
A, B>
= <
A as Div<
B>>
::Output;
二、核心结构
Ratio<Exp5, ExpPi, Exp3, Exp2>
这是一个零大小的类型,使用PhantomData来存储类型参数
通过四个类型参数表示比例因子的质因数分解:
Exp5: 5的幂次
ExpPi: π的幂次
Exp3: 3的幂次
Exp2: 2的幂次
三、主要功能
- 乘法运算
impl<
E5a, EPia, E3a, E2a, E5b, EPib, E3b, E2b>
Mul<
Ratio<
E5b, EPib, E3b, E2b>>
for Ratio<
E5a, EPia, E3a, E2a>
实现两个比例因子的乘法
结果是将对应指数相加得到的新比例因子
使用Sum类型计算各指数的和
- 除法运算
impl<
E5a, EPia, E3a, E2a, E5b, EPib, E3b, E2b>
Div<
Ratio<
E5b, EPib, E3b, E2b>>
for Ratio<
E5a, EPia, E3a, E2a>
实现两个比例因子的除法
结果是将对应指数相减得到的新比例因子
使用Diff类型计算各指数的差
- 类型别名
RatioOne: 表示单位1的比例因子 (所有指数为0)
RatioMul<A, B>: 计算两个比例乘积的结果类型
RatioDiv<A, B>: 计算两个比例商的结果类型
四、特点
零成本抽象:完全在类型系统层面进行计算,运行时无开销
类型安全:通过类型系统保证比例运算的正确性
可扩展性:可以方便地添加新的质因数类型
五、使用场景
这种设计特别适合需要精确表示各种物理单位比例的系统,例如:
时间单位转换(小时、分钟、秒)
角度单位转换(度、弧度、百分度)
其他需要精确比例关系的科学计算
注释掉的value()方法展示了如何计算比例因子的实际浮点值(基于5、π、3和2的幂次),虽然当前实现中没有使用,但可以作为调试或实际计算的基础。

浙公网安备 33010602011771号