18 个版本 (11 个重大更新)
0.13.2 | 2024年7月27日 |
---|---|
0.12.1 | 2024年4月5日 |
0.12.0 | 2023年5月15日 |
0.11.0 | 2022年8月19日 |
0.1.1 |
|
#49 在 数学
502 每月下载
用于 2 crates
95KB
1.5K SLoC
使用数量进行单元安全计算。
什么是数量?
"数量的值通常表示为数字和单位的乘积。单位是数量相关的一个特定示例,用作参考,而数字是数量值与单位的比值。"(国际度量衡局:国际单位制,第8版,2006年)
基本类型的数量是通过“惯例”定义的,它们不依赖于其他类型的数量,例如长度、质量或持续时间。
导出类型的数量,相反,被定义为其他类型数量乘以某些指数的乘积。
示例
-
体积 = 长度³
-
速度 = 长度¹ · 持续时间⁻¹
-
加速度 = 长度¹ · 持续时间⁻²
-
力 = 质量¹ · 加速度¹
每种类型的数量可能有一个特殊单位,用作所有其他单位的参考,例如米、千克和秒。其他单位然后根据它们与参考单位的关系定义。
如果一个类型的数量是从所有都具有参考单位的类型派生出来的,那么该类型的参考单位由一个公式定义,该公式遵循定义数量类型的公式。
示例
-
速度 -> 每秒米 = 米¹ · 秒⁻¹
-
加速度 -> 每秒平方米 = 米¹ · 秒⁻²
-
力 -> 牛顿 = 千克¹ · 米¹ · 秒⁻²
"度量系统"
可能有不同的系统定义数量、它们的单位和这些单位之间的关系,方式不同。
此包不直接支持此功能。对于每种类型的数量,可以有零个或恰好一个参考单位。但是,如果您有同一类型数量的不同系统的单位,您可以定义这些单位并提供在这些单位之间进行转换的机制。
基础知识:数量和单位
该包的基本功能由特性 Quantity
、HasRefUnit
、Unit
和 LinearScaledUnit
以及用于生成具体数量类型的代码的宏提供。
可以使用 proc-macro 属性 quantity
轻易地定义一种 基本 类型的数量,可选地跟随一个属性 refunit
,然后至少跟随一个属性 unit
。
该宏生成一个枚举,具有给定的单位(包括如果提供则 refunit)作为变体(同时实现特性 Unit
以及如果有参考单位则特性 LinearScaledUnit
),一个以给定结构体命名的类型,为此类型实现特性 Quantity
,如果有参考单位则实现特性 HasRefUnit
,以及一些 std 特性的实现。
此外,它为每个枚举变体创建一个常量,因此为每个单位提供一个常量。这意味着所有定义的数量中所有单位的标识符都必须是唯一的!
示例
# use quantities::prelude::*;
#[quantity]
#[ref_unit(Kilogram, "kg", KILO)]
#[unit(Milligram, "mg", MILLI, 0.000001)]
#[unit(Carat, "ct", 0.0002)]
#[unit(Gram, "g", NONE, 0.001)]
#[unit(Ounce, "oz", 0.028349523125)]
#[unit(Pound, "lb", 0.45359237)]
#[unit(Stone, "st", 6.35029318)]
#[unit(Tonne, "t", MEGA, 1000.)]
/// The quantity of matter in a physical body.
struct Mass {}
assert_eq!(MILLIGRAM.name(), "Milligram");
assert_eq!(POUND.symbol(), "lb");
assert_eq!(TONNE.si_prefix(), Some(SIPrefix::MEGA));
assert_eq!(CARAT.scale(), Amnt!(0.0002));
为了创建基于更基本数量类型的 派生 类型的数量,可以将表达式作为 proc-macro 属性 quantity
的参数,指定数量作为两个基本数量的乘积或商。
然后可以通过乘以或除以基本数量的实例来构建派生数量的实例。将定义为乘积的数量除以基本数量之一的实例,得到另一个基本数量的实例。将定义为商的数量乘以除数数量的实例,得到被除数数量的实例。
示例
# use quantities::prelude::*;
#[quantity]
#[ref_unit(Meter, "m", NONE, "Reference unit of quantity `Length`")]
#[unit(Centimeter, "cm", CENTI, 0.01, "0.01·m")]
#[unit(Kilometer, "km", KILO, 1000, "1000·m")]
#[unit(Mile, "mi", 1609.344, "8·fur")]
pub struct Length {}
#[quantity]
#[ref_unit(Second, "s", NONE, "Reference unit of quantity `Duration`")]
#[unit(Minute, "min", 60, "60·s")]
#[unit(Hour, "h", 3600, "60·min")]
pub struct Duration {}
#[quantity(Length * Length)]
#[ref_unit(Square_Meter, "m²", NONE, "Reference unit of quantity `Area`")]
#[unit(Square_Centimeter, "cm²", 0.00001, "cm²")]
#[unit(Square_Kilometer, "km²", MEGA, 1000000., "km²")]
pub struct Area {}
let a = Amnt!(3.) * METER;
let b = Amnt!(0.5) * KILOMETER;
let ab = a * b;
assert_eq!(ab, Amnt!(1500.) * SQUARE_METER);
let c = ab / (Amnt!(2.) * KILOMETER);
assert_eq!(c, Amnt!(0.75) * METER);
#[quantity(Length / Duration)]
#[ref_unit(Meter_per_Second, "m/s", NONE, "Reference unit of quantity `Speed`")]
#[unit(Miles_per_Hour, "mph", 0.44704, "mi/h")]
pub struct Speed {}
let l = Amnt!(150.) * MILE;
let t = Amnt!(1.2) * HOUR;
let v = l / t;
assert_eq!(v, Amnt!(125.) * MILES_PER_HOUR);
let d = v * Duration::new(Amnt!(3.), HOUR);
assert_eq!(d, Amnt!(375.) * MILE);
数值部分类型
该包允许为 Quantity
值的数值部分使用 float
或 fixed-point decimal
值。
内部使用类型别名 AmountT
。此别名可以通过可选功能 fpdec
(参见 功能)进行控制。
当功能 fpdec
关闭(=默认)时,AmountT
在 64 位系统上定义为 f64
或者在 32 位系统上定义为 f32
。
当功能 fpdec
激活时,AmountT
定义为 Decimal
(从 crate fpdec
导入)。
可以使用宏 Amnt!
将浮点字面值正确地转换为 AmountT
,具体取决于配置。这是通过上述描述的 proc-macro quantity
自动为单位的刻度值完成的。
实例化数量
可以通过调用函数 new
创建数量类型的实例,提供一个数量和一个单位。或者,可以乘以一个数量和一个单位。
示例
# use quantities::prelude::*;
# #[quantity]
# #[ref_unit(Kilogram, "kg", KILO)]
# #[unit(Gram, "g", NONE, 0.001)]
# struct Mass {}
let m = Mass::new(Amnt!(17.4), GRAM);
assert_eq!(m.to_string(), "17.4 g");
let m = Amnt!(17.4) * GRAM;
assert_eq!(m.to_string(), "17.4 g");
单位安全计算
如果数量类型有一个参考单位,可以通过调用方法 convert
将数量实例转换为同一类型的具有不同单位的数量实例。
示例
# use quantities::prelude::*;
# #[quantity]
# #[ref_unit(Kilogram, "kg", KILO)]
# #[unit(Carat, "ct", 0.0002)]
# #[unit(Gram, "g", NONE, 0.001)]
# struct Mass {}
let x = Mass::new(Amnt!(13.5), GRAM);
let y = x.convert(CARAT);
assert_eq!(y.to_string(), "67.5 ct");
具有相同单位的数量值始终可以相加或相减。具有不同单位的值相加或相减需要值可转换。
示例
# use quantities::prelude::*;
# #[quantity]
# #[ref_unit(Kilogram, "kg", KILO)]
# #[unit(Gram, "g", NONE, 0.001)]
# struct Mass {}
let x = Amnt!(17.4) * GRAM;
let y = Amnt!(1.407) * KILOGRAM;
let z = x + y;
assert_eq!(z.amount(), Amnt!(1424.4));
assert_eq!(z.unit(), GRAM);
let z = y + x;
assert_eq!(z.to_string(), "1.4244 kg");
数量值始终可以乘以或除以数值,保留单位。
示例
# use quantities::prelude::*;
# #[quantity]
# #[ref_unit(Kilogram, "kg", KILO)]
# #[unit(Gram, "g", NONE, 0.001)]
# struct Mass {}
let x = Amnt!(7.4);
let y = Amnt!(1.7) * KILOGRAM;
let z = x * y;
assert_eq!(z.to_string(), "12.58 kg");
常用量
该软件包提供可选模块,其中包含常用量的定义;每个都可以通过具有相应名称的功能来激活(见下文)。
箱特征
默认情况下,只有功能 std
被启用。
生态系统
- std - 当启用时,这将导致
quantities
使用标准库,以便可以使用字符串转换、格式化和打印。当禁用时,需要使用alloc
箱以及特定于系统的分配器来使用该功能。
可选依赖
-
fpdec - 当启用时,将使用
f64
或f32
代替fpdec::Decimal
作为AmountT
(见上文)。 -
serde - 当启用时,启用对
serde
的支持。
预定义量
以下功能可以启用附加模块,每个都提供预定义量。
- mass - 模块 [mass] - 量 质量
- length - 模块 [length] - 量 长度
- duration - 模块 [duration] - 量 持续时间
- area - 模块 [area] - 量 面积
- volume - 模块 [volume] - 量 体积
- speed - 模块 [speed] - 量 速度
- acceleration - 模块 [acceleration] - 量 加速度
- force - 模块 [force] - 量 力
- energy - 模块 [energy] - 量 能量
- power - 模块 [power] - 量 功率
- frequency - 模块 [frequency] - 量 频率
- datavolume - 模块 [datavolume] - 量 数据量
- datathroughput - 模块 [datathroughput] - 量 数据吞吐量
- temperature - 模块 [temperature] - 量 温度
依赖关系
~0.9–1.5MB
~29K SLoC