#维度分析 #SI 单位 #单位 #数量 #维度 #测量 #单位

nightly dimensional_quantity

使用泛型常量表达式在编译时检查度量单位

15 个版本

0.1.3 2024年5月23日
0.1.2 2024年5月16日
0.0.5 2024年5月5日
0.0.4 2023年7月21日
0.0.1-alpha.42022年11月30日

#67 in 科学

Download history 133/week @ 2024-04-30 269/week @ 2024-05-07 250/week @ 2024-05-14 133/week @ 2024-05-21 1/week @ 2024-05-28 5/week @ 2024-06-04 3/week @ 2024-06-11 41/week @ 2024-07-23 22/week @ 2024-07-30

63 每月下载量

MIT/Apache

120KB
2.5K SLoC

dimensional_quantity

维度数量:使用泛型常量表达式在编译时检查物理量的维度

用法

  • 此 crate 是 实验性 的,并使用 不稳定generic_const_exprs 功能,只能使用 nightly 工具链编译。
  • 如果您需要一个 稳定 的解决方案,请查看出色的 dimensioneduom crate。
  • 唯一实现的基础存储类型是 f64 和 f32。

要使用此 crate,首先将以下内容添加到您的 Cargo.toml

[dependencies]
dimensional_quantity = "0.1"

然后在您的 crate 中启用 generic_const_exprs 功能

 #![feature(generic_const_exprs)]

并使用 cargo +nightly

cargo +nightly build

或将包含以下内容的 rust-toolchain.toml 文件添加到您的项目中

[toolchain]
channel = "nightly"

功能

使用 Serde 进行序列化/反序列化

[dependencies]
dimensional_quantity = {version = "0.1", features = ["use_serde"]}

十进制存储类型

[dependencies]
dimensional_quantity = {version = "0.1", features = ["decimal"]}

示例

从 f64 创建维度数量


#![feature(generic_const_exprs)]

use dimensional_quantity::si::extended::f64::quantities::{Velocity};
use dimensional_quantity::si::extended::f64::units_of_measure::velocity::{MILLIMETER_PER_SECOND};

// This will create velocity of 10 m/s, default units are SI units
let v1: Velocity = Velocity::new(10.0);
// This method is constant and works also at compile time:
const SPEED_OF_SOUND: Velocity = Velocity::new(343.0);

// Various units of length are available at
// dimensional_quantity::si::extended::f64::units_of_measure::*
// Units are just constant dimensional quantities
// For example, MILLIMETER unit is defined as
// pub const MILLIMETER: Length = Length::new(1.0E-3);
// One way is using new_with_unit method:
let v2: Velocity = Velocity::new_with_unit(10_000.0, MILLIMETER_PER_SECOND);
// Another is just multiplying f64 with unit:
let v3: Velocity = 10_000.0 * MILLIMETER_PER_SECOND;

// Any of the above methods lead to the same result:
assert_eq!(v1, v2);
assert_eq!(v1, v3);

将维度数量转换回 f64

use dimensional_quantity::si::extended::f64::quantities::{Velocity};
use dimensional_quantity::si::extended::f64::units_of_measure::velocity::{MILLIMETER_PER_SECOND};

// Getting f64 value of dimensional quantity in SI units:
// Velocity of 10 m/s
let v1: Velocity = Velocity::new(10.0);
// Velocity of 343 m/s
const SPEED_OF_SOUND: Velocity = Velocity::new(343.0);

let v1_value_is_si_units = v1.get_with_si_unit();
// also possible at compile time:
const SPEED_OF_SOUND_IN_SI_UNITS:f64 = SPEED_OF_SOUND.get_with_si_unit();

assert_eq!(SPEED_OF_SOUND_IN_SI_UNITS, 343.0);
assert_eq!(v1_value_is_si_units, 10.0);

// Getting f64 value of dimensional quantity in arbitrary units is possible:
let v1_value_is_mm_per_second = v1.get_with_unit(MILLIMETER_PER_SECOND);
assert_eq!(v1_value_is_mm_per_second, 10_000.0);

使用维度数量进行数学运算


#![feature(generic_const_exprs)]

use dimensional_quantity::si::extended::f64::quantities::{Area, Energy, Length, Mass, ReciprocalLength, Velocity};
use dimensional_quantity::si::extended::f64::units_of_measure::length::{METER, MICROMETER};
use dimensional_quantity::si::extended::f64::units_of_measure::reciprocal_length::{RECIPROCAL_CENTIMETER};
use core::f64::consts::PI;
let width: Length = 5.0 * METER;
let height: Length = 8.0 * METER;
// Quantities can be multiplied or divided by f64 floating numbers,
// resulting in quantities of same dimension
let double_height: Length = height * 2.0;
let half_width = width / 2.0;

assert_eq!(double_height, Length::new(16.0));
assert_eq!(half_width, Length::new(2.5));

// Dividing f64 by dimensional quantity returns reciprocal quantity:
let red_light_wavelength: Length = 0.65 * MICROMETER;
let red_light_k: ReciprocalLength = 2.0 * PI / red_light_wavelength;
let red_light_k_in_reciprocal_cm = red_light_k.get_with_unit(RECIPROCAL_CENTIMETER);

assert_eq!(red_light_k_in_reciprocal_cm, 966_64.389_341_224_39);
// Most quantities of same dimension (except ones containing ThermodynamicTemperatures,
// that will be discussed below) can be added or subtracted:

let perimeter: Length = 2.0 * (width + height);
// AddAssign and SubAssign operators are supported
let mut width_minus_height = Length::new(0.0);
width_minus_height += width;
width_minus_height -= height;

assert_eq!(perimeter, Length::new(26.0));

// Dimensional quantities can be multiplied and divided:
let area_1: Area = width * height;
let area_2: Area = half_width * double_height;
assert_eq!(area_1, area_2);
let height_1 :Length = area_1 / width;
assert_eq!(height_1, height);

// Dimensional quantities can also be raised to an integer power during compile time
let v: Velocity = Velocity::new(10.0);
let m: Mass = Mass::new(5.0); // 5 kg
let e: Energy = m * v.powi::<2>() / 2.0;
assert_eq!(e, Energy::new(250.0));

尝试添加、减去或分配具有不匹配维度的数量会导致编译时错误

#![feature(generic_const_exprs)]
use dimensional_quantity::si::extended::{Area, Length};

let length: Length = Length::new(10.0);
let area: Area = length.powi<2>();
// Type mismatch: can not add Length and Area:
let fail_1 = length + area;
// Type mismatch: can not subtract Area from Length:
let fail_2 = length - area;
// Type mismatch: can not assign Area to Length:
let fail_3: Length = area;

创建新的数量和测试

如果某些数量或单位未在 预定义维度数量预定义度量单位 中实现,则可以定义新的数量和相应的度量单位,如下所示

#![feature(generic_const_exprs)]
use dimensional_quantity::si::extended::f64::quantities::{Information, Volume};
use dimensional_quantity::si::extended::f64::Quantity;
// New quantity: amount of information per unit of volume, standard unit of measure: Bit per cubic meter, B ⋅ m<sup>-3</sup>:
pub type VolumetricInformationDensity = Quantity<
                                                -3, // Length
                                                 0, // Mass
                                                 0, // Time
                                                 0, // ElectricCurrent
                                                 0, // ThermodynamicTemperature
                                                 0, // AmountOfSubstance
                                                 0, // LuminousIntensity
                                                 0, // TemperatureInterval
                                                 0, // Angle
                                                 0, // SolidAngle
                                                 1, // Information
                                                  >;

pub const GIGABIT_PER_CUBIC_METER: VolumetricInformationDensity = VolumetricInformationDensity::new(1.0_E9);
let information_density_1: VolumetricInformationDensity  = 5.0 * GIGABIT_PER_CUBIC_METER;
let information_density_2: VolumetricInformationDensity = Information::new(5.0_E9) / Volume::new(1.0);
assert_eq!(information_density_1, information_density_2);

量与测量单位定义

量及其对应的单位在 src/si/quantities_definition/*toml 文件中定义。

例如,面积量的定义是

name = "Area"
symbol = "Area"
snake_case_name = "area"
short_dim_formula = "L<sup>2</sup>"
long_dim_formula = "Length<sup>2</sup>"
units_formula = "m<sup>2</sup>"
[dimensions]
length = 2
mass = 0
time = 0
electric_current = 0
thermodynamic_temperature = 0
temperature_interval = 0
amount_of_substance = 0
luminous_intensity = 0
angle = 0
solid_angle = 0
information = 0

[units.SQUARE_METER]
multiplier = "1.0E0"
symbol = ""
singular = "square meter"
plural = "square meters"

[units.SQUARE_CENTIMETER]
multiplier = "1.0_E-4"
symbol = "cm²"
singular = "square centimeter"
plural = "square centimeters"

许可证

根据您的选择,许可证采用 Apache License 2.0 或 MIT 许可证(LICENSE-MIT 或 https://opensource.org/licenses/MIT)。

许可证:MIT OR Apache-2.0

依赖项

~0.5–1.2MB
~27K SLoC