【PhysUnits】1 SI Prefixes 实现解析(prefix.rs)

news2025/5/10 13:54:41

一、源码

// prefix.rs
//! SI Prefixes (国际单位制词头)
//! 
//! 提供所有标准SI词头用于单位转换,仅处理10的幂次
//! 
//! Provides all standard SI prefixes for unit conversion, handling only powers of 10.

use typenum::{
    Z0, P1, P2, P3, P6, P9, P12, P15, P18, P21, P24, P27, P30,
    N1, N2, N3, N6, N9, N12, N15, N18, N21, N24, N27, N30,
    Integer, IsEqual, Sum, Diff
};
use core::marker::PhantomData;
use core::ops::{Add, Sub, Mul, Div};

/// PrefixLike trait defines operations related to SI prefixes
/// SI词头特质定义了与SI词头相关的操作
pub trait PrefixLike {
    /// The symbol of the prefix (e.g. "k" for kilo)
    /// 词头符号(例如"k"表示千)
    const SYMBOL: &'static str;
    
    /// The exponent of the prefix (e.g. 3 for kilo which means 10^3)
    /// 词头的幂次(例如3表示千,即10^3)
    const EXPONENT: i32;
    
    /// Whether the prefix is positive (exponent > 0)
    /// 是否是正词头(幂次>0)
    const IS_POSITIVE: bool = { Self::EXPONENT > 0 };
    
    /// Whether the prefix is negative (exponent < 0)
    /// 是否是负词头(幂次<0)
    const IS_NEGATIVE: bool = { Self::EXPONENT < 0 };
}

/// Prefix struct representing a power of 10
/// 词头结构体,表示10的幂次
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Prefix<Exp: Integer>(PhantomData<Exp>);

// 实现构造函数
impl<Exp: Integer> Prefix<Exp> {
    /// Create a new Prefix instance
    /// 创建一个新的词头实例
    pub fn new() -> Self {
        Prefix(PhantomData)
    }
}

// 为各类型实现PrefixLike
// Implement PrefixLike for various types

// 无词头 / No prefix
impl PrefixLike for Prefix<Z0> {
    const SYMBOL: &'static str = "";
    const EXPONENT: i32 = 0;
}

// 正词头 / Positive prefixes
impl PrefixLike for Prefix<P1> {
    const SYMBOL: &'static str = "da";
    const EXPONENT: i32 = 1;
}

impl PrefixLike for Prefix<P2> {
    const SYMBOL: &'static str = "h";
    const EXPONENT: i32 = 2;
}

impl PrefixLike for Prefix<P3> {
    const SYMBOL: &'static str = "k";
    const EXPONENT: i32 = 3;
}

impl PrefixLike for Prefix<P6> {
    const SYMBOL: &'static str = "M";
    const EXPONENT: i32 = 6;
}

impl PrefixLike for Prefix<P9> {
    const SYMBOL: &'static str = "G";
    const EXPONENT: i32 = 9;
}

impl PrefixLike for Prefix<P12> {
    const SYMBOL: &'static str = "T";
    const EXPONENT: i32 = 12;
}

impl PrefixLike for Prefix<P15> {
    const SYMBOL: &'static str = "P";
    const EXPONENT: i32 = 15;
}

impl PrefixLike for Prefix<P18> {
    const SYMBOL: &'static str = "E";
    const EXPONENT: i32 = 18;
}

impl PrefixLike for Prefix<P21> {
    const SYMBOL: &'static str = "Z";
    const EXPONENT: i32 = 21;
}

impl PrefixLike for Prefix<P24> {
    const SYMBOL: &'static str = "Y";
    const EXPONENT: i32 = 24;
}

impl PrefixLike for Prefix<P27> {
    const SYMBOL: &'static str = "R";
    const EXPONENT: i32 = 27;
}

impl PrefixLike for Prefix<P30> {
    const SYMBOL: &'static str = "Q";
    const EXPONENT: i32 = 30;
}

// 负词头 / Negative prefixes
impl PrefixLike for Prefix<N1> {
    const SYMBOL: &'static str = "d";
    const EXPONENT: i32 = -1;
}

impl PrefixLike for Prefix<N2> {
    const SYMBOL: &'static str = "c";
    const EXPONENT: i32 = -2;
}

impl PrefixLike for Prefix<N3> {
    const SYMBOL: &'static str = "m";
    const EXPONENT: i32 = -3;
}

impl PrefixLike for Prefix<N6> {
    const SYMBOL: &'static str = "μ";
    const EXPONENT: i32 = -6;
}

impl PrefixLike for Prefix<N9> {
    const SYMBOL: &'static str = "n";
    const EXPONENT: i32 = -9;
}

impl PrefixLike for Prefix<N12> {
    const SYMBOL: &'static str = "p";
    const EXPONENT: i32 = -12;
}

impl PrefixLike for Prefix<N15> {
    const SYMBOL: &'static str = "f";
    const EXPONENT: i32 = -15;
}

impl PrefixLike for Prefix<N18> {
    const SYMBOL: &'static str = "a";
    const EXPONENT: i32 = -18;
}

impl PrefixLike for Prefix<N21> {
    const SYMBOL: &'static str = "z";
    const EXPONENT: i32 = -21;
}

impl PrefixLike for Prefix<N24> {
    const SYMBOL: &'static str = "y";
    const EXPONENT: i32 = -24;
}

impl PrefixLike for Prefix<N27> {
    const SYMBOL: &'static str = "r";
    const EXPONENT: i32 = -27;
}

impl PrefixLike for Prefix<N30> {
    const SYMBOL: &'static str = "q";
    const EXPONENT: i32 = -30;
}

// ========== 基本操作实现 ==========
// ========== Basic Operations Implementation ==========

/// 实现词头乘法 (10^a * 10^b = 10^(a+b))
/// Implements prefix multiplication (10^a * 10^b = 10^(a+b))
impl<Ea, Eb> Mul<Prefix<Eb>> for Prefix<Ea>
where
    Ea: Integer + Add<Eb>,
    Eb: Integer,
    Sum<Ea, Eb>: Integer,
{
    type Output = Prefix<Sum<Ea, Eb>>;
    
    fn mul(self, _: Prefix<Eb>) -> Self::Output {
        Prefix::new()
    }
}

/// 实现词头除法 (10^a / 10^b = 10^(a-b))
/// Implements prefix division (10^a / 10^b = 10^(a-b))
impl<Ea, Eb> Div<Prefix<Eb>> for Prefix<Ea>
where
    Ea: Integer + Sub<Eb>,
    Eb: Integer,
    Diff<Ea, Eb>: Integer,
{
    type Output = Prefix<Diff<Ea, Eb>>;
    
    fn div(self, _: Prefix<Eb>) -> Self::Output {
        Prefix::new()
    }
}

// ========== 实用类型别名 ==========
// ========== Useful Type Aliases ==========

pub type NoPrefix = Prefix<Z0>;
pub type Deca = Prefix<P1>;
pub type Hecto = Prefix<P2>;
pub type Kilo = Prefix<P3>;
pub type Mega = Prefix<P6>;
pub type Giga = Prefix<P9>;
pub type Tera = Prefix<P12>;
pub type Peta = Prefix<P15>;
pub type Exa = Prefix<P18>;
pub type Zetta = Prefix<P21>;
pub type Yotta = Prefix<P24>;
pub type Ronna = Prefix<P27>;
pub type Quetta = Prefix<P30>;

pub type Deci = Prefix<N1>;
pub type Centi = Prefix<N2>;
pub type Milli = Prefix<N3>;
pub type Micro = Prefix<N6>;
pub type Nano = Prefix<N9>;
pub type Pico = Prefix<N12>;
pub type Femto = Prefix<N15>;
pub type Atto = Prefix<N18>;
pub type Zepto = Prefix<N21>;
pub type Yocto = Prefix<N24>;
pub type Ronto = Prefix<N27>;
pub type Quecto = Prefix<N30>;

/// 词头乘法结果类型 / Prefix multiplication result type
pub type PrefixMul<A, B> = <A as Mul<B>>::Output;

/// 词头除法结果类型 / Prefix division result type
pub type PrefixDiv<A, B> = <A as Div<B>>::Output;

/// 词头相等判断类型 / Prefix equality comparison type
pub type PrefixEq<A, B> = <A as IsEqual<B>>::Output;

// ========== 调试和测试代码 ==========
// ========== Debug and Test Code ==========

#[cfg(test)]
mod tests {
    use super::*;
    
    /// 测试词头属性和基本操作
    /// Test prefix properties and basic operations
    #[test]
    fn test_prefix_properties() {
        assert_eq!(Kilo::SYMBOL, "k");
        assert_eq!(Kilo::EXPONENT, 3);
        assert!(Kilo::IS_POSITIVE);
        assert!(!Kilo::IS_NEGATIVE);
        
        assert_eq!(Milli::SYMBOL, "m");
        assert_eq!(Milli::EXPONENT, -3);
        assert!(!Milli::IS_POSITIVE);
        assert!(Milli::IS_NEGATIVE);
    }
    
    #[test]
    fn test_prefix_multiplication() {
        let kilo = Prefix::<P3>::new();
        let milli = Prefix::<N3>::new();
        
        // k * m = 10^3 * 10^-3 = 10^0
        let result = kilo * milli;
        assert_eq!(result, Prefix::<Z0>::new());
        
        // M * k = 10^6 * 10^3 = 10^9 (Giga)
        let mega = Prefix::<P6>::new();
        let kilo = Prefix::<P3>::new();
        let result = mega * kilo;
        assert_eq!(result, Prefix::<P9>::new());
    }
    
    #[test]
    fn test_prefix_division() {
        let kilo = Prefix::<P3>::new();
        let milli = Prefix::<N3>::new();
        
        // k / m = 10^3 / 10^-3 = 10^6 (Mega)
        let result = kilo / milli;
        assert_eq!(result, Prefix::<P6>::new());
        
        // m / k = 10^-3 / 10^3 = 10^-6 (Micro)
        let result = milli / kilo;
        assert_eq!(result, Prefix::<N6>::new());
    }
    
    #[test]
    fn test_type_aliases() {
        assert_eq!(<PrefixMul<Kilo, Milli> as PrefixLike>::EXPONENT, 0);
        assert_eq!(<PrefixDiv<Mega, Kilo> as PrefixLike>::EXPONENT, 3);
    }
}

/// 调试输出实现
/// Debug output implementation
impl<Exp: Integer> core::fmt::Display for Prefix<Exp>
where
    Prefix<Exp>: PrefixLike,
{
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "Prefix({}, 10^{})", Self::SYMBOL, Self::EXPONENT)
    }
}

二、核心结构

pub trait PrefixLike {
    const SYMBOL: &'static str;
    const EXPONENT: i32;
    const IS_POSITIVE: bool = { Self::EXPONENT > 0 };
    const IS_NEGATIVE: bool = { Self::EXPONENT < 0 };
}

三、类型定义示例

// 正词头
pub type Kilo = Prefix<P3>;    // 10³
pub type Mega = Prefix<P6>;    // 10⁶

// 负词头  
pub type Milli = Prefix<N3>;   // 10⁻³
pub type Micro = Prefix<N6>;  // 10⁻⁶

四、运算实现

// 乘法实现
impl<Ea, Eb> Mul<Prefix<Eb>> for Prefix<Ea>
where
    Ea: Integer + Add<Eb>,
    Eb: Integer,
    Sum<Ea, Eb>: Integer,
{
    type Output = Prefix<Sum<Ea, Eb>>;
    
    fn mul(self, _: Prefix<Eb>) -> Self::Output {
        Prefix::new()
    }
}

五、测试用例

#[test]
fn test_prefix_multiplication() {
    let kilo = Prefix::<P3>::new();
    let milli = Prefix::<N3>::new();
    let result = kilo * milli;  // 应得到无前缀
    assert_eq!(result, Prefix::<Z0>::new());
}

六、关键特性

  1. 零成本抽象 - 所有计算在编译期完成
  2. 类型安全 - 通过类型系统保证运算合法性
  3. 完整覆盖 - 支持所有标准SI词头
  4. 可组合性 - 支持词头间的各种运算

七、使用示例

let distance = 1.0 * Kilo::new();  // 1千米
let length = distance * Milli::new();  // 转换为米

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2372351.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue 2.0 详解全教程(含 Axios 封装 + 路由守卫 + 实战进阶)

目录 一、Vue 2.0 简介1.1 什么是 Vue&#xff1f;1.2 Vue 2.x 的主要特性 二、快速上手2.1 引入 Vue2.2 创建第一个 Vue 实例 三、核心概念详解3.1 模板语法3.2 数据绑定3.3 事件绑定3.4 计算属性 & 侦听器 四、组件系统4.1 定义全局组件4.2 单文件组件&#xff08;*.vue …

依赖关系-根据依赖关系求候选码

关系模式R&#xff08;U, F&#xff09;, U{}&#xff0c;F是R的函数依赖集&#xff0c;可以将属性分为4类&#xff1a; L: 仅出现在依赖集F左侧的属性 R: 仅出现在依赖集F右侧的属性 LR: 在依赖集F左右侧都出现的属性 NLR: 在依赖集F左右侧都未出现的属性 结论1: 若X是L类…

uniapp-商城-47-后台 分类数据的生成(通过数据)

在第46章节中&#xff0c;我们为后台数据创建了分类的数据表结构schema&#xff0c;使得可以通过后台添加数据并保存&#xff0c;同时使用云函数进行数据库数据的读取。文章详细介绍了如何通过前端代码实现分类管理功能&#xff0c;包括获取数据、添加、更新和删除分类。主要代…

java-----------------多态

多态&#xff0c;当前指的是 java 所呈现出来的一个对象 多态 定义 多态是指同一个行为具有多个不同表现形式或形态的能力。在面向对象编程中&#xff0c;多态通过方法重载和方法重写来实现。 强弱类型语言 javascript 或者python 是弱类型语言 C 语言&#xff0c;或者 C…

【文档智能】开源的阅读顺序(Layoutreader)模型使用指南

一年前&#xff0c;笔者基于开源了一个阅读顺序模型&#xff08;《【文档智能】符合人类阅读顺序的文档模型-LayoutReader及非官方权重开源》&#xff09;&#xff0c; PDF解析并结构化技术路线方案及思路&#xff0c;文档智能专栏 阅读顺序检测旨在捕获人类读者能够自然理解的…

Edu教育邮箱申请2025年5月

各位好&#xff0c;这里是aigc创意人竹相左边 如你所见&#xff0c;这里是第3部分 现在是选择大学的学科专业 选专业的时候记得考虑一下当前的时间日期。 比如现在是夏天&#xff0c;所以你选秋天入学是合理的。

STM32-TIM定时中断(6)

目录 一、TIM介绍 1、TIM简介 2、定时器类型 3、基本定时器 4、通用定时器 5、定时中断基本结构 6、时基单元的时序 &#xff08;1&#xff09;预分频器时序 &#xff08;2&#xff09;计数器时序 7、RCC时钟树 二、定时器输出比较功能&#xff08;PWM&#xff09; …

Modbus RTU 详解 + FreeMODBUS移植(附项目源码)

文章目录 前言一、Modbus RTU1.1 通信方式1.2 模式特点1.3 数据模型1.4 常用功能码说明1.5 异常响应码1.6 通信帧格式1.6.1 示例一&#xff1a;读取保持寄存器&#xff08;功能码 0x03&#xff09;1.6.2 示例二&#xff1a;写单个线圈&#xff08;功能码 0x05&#xff09;1.6.3…

对称加密算法(AES、ChaCha20和SM4)Python实现——密码学基础(Python出现No module named “Crypto” 解决方案)

文章目录 一、对称加密算法基础1.1 对称加密算法的基本原理1.2 对称加密的主要工作模式 二、AES加密算法详解2.1 AES基本介绍2.2 AES加密过程2.3 Python中实现AES加密Python出现No module named “Crypto” 解决方案 2.4 AES的安全考量 三、ChaCha20加密算法3.1 ChaCha20基本介…

【软件设计师:存储】16.计算机存储系统

一、主存储器 存储器是计算机系统中的记忆设备,用来存放程序和数据。 计算机中全部信息,包括输入的原始数据、计算机程序、中间运 行结果和最终运行结果都保存在存储器中。 存储器分为: 寄存器Cache(高速缓冲存储器)主存储器辅存储器一、存储器的存取方式 二、存储器的性…

WebRTC通信原理与流程

1、服务器与协议相关 1.1 STUN服务器 图1.1.1 STUN服务器在通信中的位置图 1.1.1 STUN服务简介 STUN&#xff08;Session Traversal Utilities for NAT&#xff0c;NAT会话穿越应用程序&#xff09;是一种网络协议&#xff0c;它允许位于NAT&#xff08;或多重 NAT&#xff09;…

Java版ERP管理系统源码(springboot+VUE+Uniapp)

ERP系统是企业资源计划&#xff08;Enterprise Resource Planning&#xff09;系统的缩写&#xff0c;它是一种集成的软件解决方案&#xff0c;用于协调和管理企业内各种关键业务流程和功能&#xff0c;如财务、供应链、生产、人力资源等。它的目标是帮助企业实现资源的高效利用…

Redis总结(六)redis持久化

本文将简单介绍redis持久化的两种方式 redis提供了两种不同级别的持久化方式&#xff1a; RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储.AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保…

PMIC电源管理模块的PCB设计

目录 PMU模块简介 PMU的PCB设计 PMU模块简介 PMIC&#xff08;电源管理集成电路&#xff09;是现代电子设备的核心模块&#xff0c;负责高效协调多路电源的转换、分配与监控。它通过集成DC-DC降压/升压、LDO线性稳压、电池充电管理、功耗状态切换等功能&#xff0c;替代传统分…

华为云Flexus+DeepSeek征文|DeepSeek-V3商用服务开通教程

目录 DeepSeek-V3/R1商用服务开通使用感受 DeepSeek-V3/R1商用服务开通 1、首先需要访问ModelArts Studio_MaaS_大模型即服务_华为云 2、在网站右上角登陆自己的华为云账号&#xff0c;如果没有华为云账号的话&#xff0c;则需要自己先注册一个。 3、接着点击ModelArts Stu…

Qt—鼠标移动事件的趣味小程序:会移动的按钮

1.项目目标 本次根据Qt的鼠标移动事件实现一个趣味小程序&#xff1a;当鼠标移动到按钮时&#xff0c;按钮就会随机出现在置&#xff0c;以至于根本点击不到按钮。​​​​​ 2.项目步骤 首先现在ui界面设计控件(也可以用代码的方式创建&#xff0c;就不多说了) 第一个按钮不需…

鞋样设计软件

Sxy 64鞋样设计软件是一款专业级鞋类设计工具 专为鞋业设计师与制鞋企业开发 该软件提供全面的鞋样设计功能 包括二维开版 三维建模 放码排料等核心模块 支持从草图构思到成品输出的完整设计流程 内置丰富的鞋型数据库与部件库 可快速生成各种鞋款模板 软件采用智能放码技术 精…

LeRobot 项目部署运行逻辑(六)——visualize_dataset_html.py/visualize_dataset.py

可视化脚本包括了两个方法&#xff1a;远程下载 huggingface 上的数据集和使用本地数据集 脚本主要使用两个&#xff1a; 目前来说&#xff0c;ACT 采集训练用的是统一时间长度的数据集&#xff0c;此外&#xff0c;这两个脚本最大的问题在于不能裁剪&#xff0c;这也是比较好…

Windows Server 2025开启GPU分区(GPU-P)部署DoraCloud云桌面

本文描述在ShareStation工作站虚拟化方案的部署过程。 将服务器上部署 Windows Server、DoraCloud&#xff0c;并创建带有vGPU的虚拟桌面。 GPU分区技术介绍 GPU-P&#xff08;GPU Partitioning&#xff09; 是微软在 Windows 虚拟化平台&#xff08;如 Hyper-V&#xff09;中…

TCP套接字通信核心要点

TCP套接字通信核心要点 通信模型架构 客户端-服务端模型 CS架构&#xff1a;客户端发起请求&#xff0c;服务端响应和处理请求双向通道&#xff1a;建立连接后实现全双工通信 服务端搭建流程 核心步骤 创建套接字 int server socket(AF_INET, SOCK_STREAM, 0); 参数说明&am…