10个版本
0.2.3 | 2024年8月16日 |
---|---|
0.2.2 | 2023年11月8日 |
0.2.1 | 2022年8月19日 |
0.1.5 | 2022年6月26日 |
0.1.3 | 2021年10月21日 |
#21 in 值格式化
2,969 每月下载量
用于 3 crates
94KB
1K SLoC
si-scale
根据SI(国际单位制)格式化值。
版本要求:rustc 1.74+
[dependencies]
si-scale = "0.2"
概述
此crate使用SI尺度格式化数字:从1 y(yocto,即1e-24)到1 Y(Yotta,即1e24)。
它与伟大的human-repr具有相同的目的,但平衡不同
- 此crate在调用位置产生更简洁的代码
- 它赋予你对输出的更多控制权。如本页稍后所示,您可以轻松扩展它以处理吞吐量等(认真地说,请见下文)
- 但它只作用于数字,因此它不会阻止您使用函数在持续时间值上打印米(而human-repr做得很好)。
入门
要使用此crate,请使用以下预定义辅助函数之一,或自行构建。
基本示例
use si_scale::helpers::{seconds, seconds3};
let actual = format!("{}", seconds(1.3e-5));
let expected = "13 µs";
assert_eq!(actual, expected);
let actual = format!("{}", seconds3(1.3e-5));
let expected = "13.000 µs";
assert_eq!(actual, expected);
预定义辅助函数
辅助函数使用以下命名约定
- 名称表示要使用的单位
- 数字后缀表示浮点数的十进制位数
- 下划线后缀表示使用“千位分组”的数字
但您在编写自己的函数时可以偏离这一点。
目前辅助函数有
辅助函数 | 输入 | 输出 |
---|---|---|
number_() |
1.234567 , 1515 |
1.234_567 , 1_515 |
--- | --- | --- |
秒() |
1.234567e-6 , 16e-3 |
1.234567 µs , 16 ms |
秒数3() |
1.234567e-6 , 16e-3 |
1.235 µs , 16.000 ms |
--- | --- | --- |
字节() |
1234567 |
1.234567 MB |
字节_() |
1234567 |
1_234_567B |
字节1() |
2.3 *1e12 |
2.3 TB |
字节2() |
2.3 *1e12 |
2.30 TB |
--- | --- | --- |
bi字节() |
1024 * 1024 * 1.25 |
1.25MiB |
bi字节1() |
1024 * 1024 * 1.25 |
1.3MiB |
bi字节2() |
1024 * 1024 * 1.25 |
1.25MiB |
自定义辅助函数 - BYOU (自带单位)
要定义自己的格式函数,请使用 scale_fn!()
宏。此crate中所有预定义的辅助函数都是使用此宏定义的。
辅助函数 | 尾数 | 前缀约束 | 基数 | 分组 | 输入 | 输出 |
---|---|---|---|---|---|---|
number_() |
"{}" |
仅单位 |
B1000 | _ |
1.234567 , 1515 |
1.234_567 , 1_515 |
--- | -- | --- | --- | --- | --- | --- |
秒() |
"{}" |
单位和以下 |
B1000 | 无 | 1.234567e-6 , 16e-3 |
1.234567 µs , 16 ms |
秒数3() |
"{:.3}" |
单位和以下 |
B1000 | 无 | 1.234567e-6 , 16e-3 |
1.235 µs , 16.000 ms |
--- | -- | --- | --- | --- | --- | --- |
字节() |
"{}" |
单位和以上 |
B1000 | 无 | 1234567 |
1.234567 MB |
字节_() |
"{}" |
仅单位 |
B1000 | _ |
1234567 |
1_234_567B |
字节1() |
"{:.1}" |
单位和以上 |
B1000 | 无 | 2.3 *1e12 |
2.3 TB |
字节2() |
"{:.2}" |
单位和以上 |
B1000 | 无 | 2.3 *1e12 |
2.30 TB |
--- | -- | --- | --- | --- | --- | --- |
bi字节() |
"{}" |
单位和以上 |
B1024 | 无 | 1024 * 1024 * 1.25 |
1.25MiB |
bi字节1() |
"{:.1}" |
单位和以上 |
B1024 | 无 | 1024 * 1024 * 1.25 |
1.3MiB |
bi字节2() |
"{:.2}" |
单位和以上 |
B1024 | 无 | 1024 * 1024 * 1.25 |
1.25MiB |
附加表列显示了底层控件。
"尾数"列
它是一个格式字符串,仅在缩放后对尾数起作用。例如,"{}"
将显示所有数字的值或如果它是一个整数则没有数字,而例如 "{:.1}"
将始终显示一个小数。
"前缀约束"列
简而言之,这允许以令人惊讶的缩放表示值:例如,你永远不会写 1.2 ksec
,但总是 1200 sec
或 1.2e3 sec
。同样,你永远不会写 2 mB
,但总是 0.002 B
或 2e-3 B
。
因此,这里的“单位”一词指的是单位缩放(1
),与测量单位无关。它限制了值的可能缩放
UnitOnly
表示提供的值不会缩放:如果你提供一个大于1000的值,比如说1234,它将被打印为1234。UnitAndAbove
表示提供的值只能使用更高的缩放,例如16 GB
但永远不能是4.3 µB
。UnitAndBelow
表示提供的值只能使用较低的缩放,例如1.3 µsec
但不能是16 Gsec
。
"基数"列
基数B1000表示1k = 1000,基数B1024表示1k = 1024。这在IEC文档中定义。如果你将基数设置为B1024
,尾数将适当地缩放,但在大多数情况下,你将使用B1000
。
"分组"列
分组是指“千位分组”;提供的字符将被使用(例如,1234显示为1_234),如果没有提供,则值将显示为1234。
示例 - 如何定义kibits/s的辅助函数
例如,让我们定义一个每秒比特数的格式化函数,该函数以两位小数打印尾数,并使用1024为基数(其中1千比特=1024)。请注意,尽管我们在单独的模块中定义了此函数,但这不是必需的。
mod unit_fmt {
use si_scale::scale_fn;
use si_scale::prelude::Value;
// defines the `bits_per_sec()` function
scale_fn!(bits_per_sec,
base: B1024,
constraint: UnitAndAbove,
mantissa_fmt: "{:.2}",
groupings: '_',
unit: "bit/s",
doc: "Return a string with the value and its si-scaled unit of bit/s.");
}
use unit_fmt::bits_per_sec;
fn main() {
let x = 2.1 * 1024 as f32;
let actual = format!("throughput: {:>15}", bits_per_sec(x));
let expected = "throughput: 2.10 kibit/s";
assert_eq!(actual, expected);
let x = 2;
let actual = format!("throughput: {}", bits_per_sec(x));
let expected = "throughput: 2.00 bit/s";
assert_eq!(actual, expected);
}
您可以通过省略宏的groupings
参数来不分隔千位。
SI单位换算 - 开发者文档
基数=1000时,1千=1000,1兆=1_000_000,1毫=0.001,1微=0.000_001,等等。
最小值(包含) | 最大值(不包含) | 量级 | 前缀 |
---|---|---|---|
.. | .. | -24 | 前缀::尧托 |
.. | .. | -21 | 前缀::泽托 |
.. | .. | -18 | 前缀::阿托 |
.. | .. | -15 | 前缀::飞托 |
.. | .. | -12 | 前缀::皮科 |
.. | .. | -9 | 前缀::纳诺 |
0.000_001 | 0.001 | -6 | 前缀::微米 |
0.001 | 1 | -3 | 前缀::毫微 |
1 | 1_000 | 0 | 前缀::单位 |
1000 | 1_000_000 | 3 | 前缀::千 |
1_000_000 | 1_000_000_000 | 6 | 前缀::兆 |
.. | .. | 9 | 前缀::吉 |
.. | .. | 12 | 前缀::太 |
.. | .. | 15 | 前缀::拍 |
.. | .. | 18 | 前缀::艾 |
.. | .. | 21 | 前缀::泽 |
.. | .. | 24 | 前缀::约 |
基数通常是1000,但也可以是1024(比字节)。
基数=1024时,1千比特=1024,1兆比特=1024 * 1024,等等。
API概述
中心表示形式是Value
类型,它包含
- 尾数,
- SI单位前缀(如“千”,“兆”等),
- 以及基数,它表示“1千”表示1000(最常见)和“1千”表示1024(对于kiB,MiB等)的情况。
此crate提供2个API:一个低级API和一个高级API,方便使用。
对于低级API,典型用例是
-
首先将数字解析为
Value
。为此,您必须指定基数,并可能对SI尺度施加某些约束。请参阅Value::new()
和Value::new_with()
-
然后通过自行格式化尾数和前缀(实现
fmt::Display
特质)或使用提供的格式化程序来显示Value
。
对于高级API,典型用例是
-
使用提供的函数解析并显示数字,例如
bibytes()
、bytes()
或seconds()
,它们将为每个数字选择最合适的SI尺度。 -
如果您希望获得与低级API相同的控制粒度(例如,以某种方式约束尺度、使用某些基数、特定的尾数格式化),则可以使用提供的宏
scale_fn!()
构建自定义函数。例如,如bibytes()
、bytes()
、seconds()
等现有函数都是使用此相同宏构建的。
高级API
函数 seconds3()
将一个数字解析为一个 Value
,并使用三位小数和适用于秒的适当比例(UnitAndBelow
)进行显示,这样就不会输出诸如千秒之类的无意义比例。函数 seconds()
执行相同的操作,但使用默认的格式("{}"
)来格式化尾数,因此对于整数值的尾数不打印小数。
use si_scale::helpers::{seconds, seconds3};
let actual = format!("result is {:>15}", seconds(1234.5678));
let expected = "result is 1234.5678 s";
assert_eq!(actual, expected);
let actual = format!("result is {:>10}", seconds3(12.3e-7));
let expected = "result is 1.230 µs";
assert_eq!(actual, expected);
函数 bytes()
以基数 1000 将一个数字解析为一个 Value
,并使用一位小数和适用于字节的适当比例(UnitAndAbove
)进行显示,这样就不会出现诸如毫字节之类的无意义比例。
use si_scale::helpers::{bytes, bytes1};
let actual = format!("result is {}", bytes1(12_345_678));
let expected = "result is 12.3 MB";
assert_eq!(actual, expected);
let actual = format!("result is {:>10}", bytes(16));
let expected = "result is 16 B";
assert_eq!(actual, expected);
let actual = format!("result is {}", bytes(0.12));
let expected = "result is 0.12 B";
assert_eq!(actual, expected);
函数 bibytes1()
以基数 1024 将一个数字解析为一个 Value
,并使用一位小数和适用于字节的适当比例(UnitAndAbove
)进行显示,这样就不会出现诸如毫字节之类的无意义比例。
use si_scale::helpers::{bibytes, bibytes1};
let actual = format!("result is {}", bibytes1(12_345_678));
let expected = "result is 11.8 MiB";
assert_eq!(actual, expected);
let actual = format!("result is {}", bibytes(16 * 1024));
let expected = "result is 16 kiB";
assert_eq!(actual, expected);
let actual = format!("result is {:>10}", bibytes1(16));
let expected = "result is 16.0 B";
assert_eq!(actual, expected);
let actual = format!("result is {}", bibytes(0.12));
let expected = "result is 0.12 B";
assert_eq!(actual, expected);
低级 API
使用 Value::new()
创建 Value
低级函数 Value::new()
将任何可转换为 f64 的数字转换为使用基数 1000 的 Value
。结构体 Value
实现了 From
以处理常见数字,并将它们委托给 Value::new()
,因此在实践中它们是等价的。以下是一些示例。
use std::convert::From;
use si_scale::prelude::*;
let actual = Value::from(0.123);
let expected = Value {
mantissa: 123f64,
prefix: Prefix::Milli,
base: Base::B1000,
};
assert_eq!(actual, expected);
assert_eq!(Value::new(0.123), expected);
let actual: Value = 0.123.into();
assert_eq!(actual, expected);
let actual: Value = 1300i32.into();
let expected = Value {
mantissa: 1.3f64,
prefix: Prefix::Kilo,
base: Base::B1000,
};
assert_eq!(actual, expected);
let actual: Vec<Value> = vec![0.123f64, -1.5e28]
.iter().map(|n| n.into()).collect();
let expected = vec![
Value {
mantissa: 123f64,
prefix: Prefix::Milli,
base: Base::B1000,
},
Value {
mantissa: -1.5e4f64,
prefix: Prefix::Yotta,
base: Base::B1000,
},
];
assert_eq!(actual, expected);
如最后一个示例所示,对于超出 SI 前缀的比例值,使用最接近的 SI 前缀来表示。
使用 Value::new_with()
创建 Value
低级 Value::new_with()
与 Value::new()
类似,但也期望一个基数和您想要使用的比例约束。与简单的 Value::new()
相比,这允许使用基数 1024 的比例(例如 kiB、MiB 等)并防止秒的更高比例或字节等整数量单位的更低比例(例如,避免将 1300 秒写成 1.3 ks 或将 0.415 B 写成 415 mB)。
use si_scale::prelude::*;
// Assume this is seconds, no kilo-seconds make sense.
let actual = Value::new_with(1234, Base::B1000, Constraint::UnitAndBelow);
let expected = Value {
mantissa: 1234f64,
prefix: Prefix::Unit,
base: Base::B1000,
};
assert_eq!(actual, expected);
不用担心冗长,以下解析器有助于解决这个问题。
格式化值
在这个示例中,数字 x
被转换为值并使用最合适的 SI 前缀进行显示。用户选择将前缀约束为小于 Unit
(1),因为千秒没有意义。
use si_scale::format_value;
use si_scale::{value::Value, base::Base, prefix::Constraint};
let x = 1234.5678;
let v = Value::new_with(x, Base::B1000, Constraint::UnitAndBelow);
let unit = "s";
let actual = format!(
"result is {}{u}",
format_value!(v, "{:.5}", groupings: '_'),
u = unit
);
let expected = "result is 1_234.567_80 s";
assert_eq!(actual, expected);
运行代码覆盖率
安装 llvm-tools-preview 组件和 grcov
rustup component add llvm-tools-preview
cargo install grcov
安装夜间版本
rustup toolchain install nightly
以下make调用将切换到夜间版本运行测试,并使用Cargo输出HTML覆盖率报告到./coverage/
make coverage
覆盖率报告位于./coverage/index.html
许可证
根据您的选择,许可协议为以下之一
。
贡献
除非您明确声明,否则任何有意提交以供包含在作品中的贡献,如Apache-2.0许可证中定义的,将根据上述方式双重许可,不附加任何额外条款或条件。