#numbers #string-format #representation #format #convert #num #human-readable

format_num

根据格式指定器迷你语言将数字格式化为字符串的多种表示形式

1 个不稳定版本

0.1.0 2020年4月20日

#115值格式化

Download history 723/week @ 2024-03-14 780/week @ 2024-03-21 718/week @ 2024-03-28 713/week @ 2024-04-04 629/week @ 2024-04-11 721/week @ 2024-04-18 780/week @ 2024-04-25 768/week @ 2024-05-02 1040/week @ 2024-05-09 709/week @ 2024-05-16 837/week @ 2024-05-23 1291/week @ 2024-05-30 1165/week @ 2024-06-06 1705/week @ 2024-06-13 1918/week @ 2024-06-20 1240/week @ 2024-06-27

6,399 每月下载量
14 个crates中(8个直接)使用

MIT/Apache

58KB
905

format_num

动态将数字格式化为人类可读形式。

你遇到过Rust无法以你期望的方式表示数字的情况吗?

for i in 1..=10 {
    println!("{}", 0.1 * i as f64);
}

你会得到这个

0.1
0.2
0.30000000000000004
0.4
0.5
0.6000000000000001
0.7000000000000001
0.8
0.9
1

这实际上不是Rust的问题,而是浮点数在二进制中的表示方式

但是,舍入误差并不是定制数字格式的唯一原因。数字表应该格式化一致以便比较;上面的1.0比1.0更好。大数字可能需要分组数字(例如42,000)或以科学或公制符号(4.2e+4,42k)表示。报告的数值结果应四舍五入到有效数字(4021变为4000)等。

解析器基于Python 3的格式指定器迷你语言 (PEP3101),并进行了一些小的实现细节修改。

格式指定器的通用形式是

[[fill]align][sign][symbol][0][width][,][.precision][type]

填充字符可以是任何字符。填充字符的存在是通过其后的对齐字符来表示的,它必须是以下之一

> - 强制字段在可用空间内右对齐。

< - 强制字段在可用空间内左对齐。

^ - 强制字段在可用空间内居中对齐。

= - 类似于 >,但可以在任何填充的左侧放置任何符号和符号。

符号可以是

- - 零或正数没有符号,负数有一个负号(默认行为)。

+ - 零或正数有一个加号,负数有一个减号。

(空格)- 零或正数,负数则带减号。

符号可以是

#选项会导致使用“交替形式”进行转换。对于不同类型,交替形式的定义不同。对于整数,当使用二进制(b)、八进制(oO)或十六进制(xX)输出时,此选项会在输出值前添加相应的“0b”、“0o”、“0O”或“0x”前缀。对于浮点数,交替形式会导致转换结果总是包含小数点字符,即使后面没有数字。

零(0)选项启用零填充;这会隐式地将填充设置为0并对齐设置为=。

宽度定义最小字段宽度;如果没有指定,则宽度将由内容决定。

逗号(,)选项启用使用分组分隔符,例如千位分隔符。

根据类型精度要么表示小数点后的数字位数(类型f%),要么表示有效数字的位数(类型es)。如果未指定精度,则默认为所有类型的6位。对于整数格式(类型bodxX),精度将被忽略。

可用的类型值包括

e - 指数表示法。

f - 固定点表示法。

s - 带有SI前缀的十进制表示法,四舍五入到有效数字。

% - 乘以100,然后使用带有百分号的十进制表示法。

b - 二进制表示法,四舍五入到整数。

o - 八进制表示法,四舍五入到整数。

d - 十进制表示法,四舍五入到整数。

x - 十六进制表示法,使用小写字母,四舍五入到整数。

X - 十六进制表示法,使用大写字母,四舍五入到整数。

示例

use format_num::{NumberFormat, format_num};

fn main() {
    let num = NumberFormat::new();
    let format_spec = "+14d";
    assert_eq!(num.format(".1f", 0.06), "0.1");
    assert_eq!(num.format("#.0f", 10.1), "10."); // float alternate form (always show a decimal point)
    assert_eq!(num.format("#b", 3), "0b11");
    assert_eq!(num.format("b", 3), "11");
    assert_eq!(num.format(format_spec, 2_147_483_647), "   +2147483647");
    
    // Or, you can use a macro for simplicity
    assert_eq!(format_num!("#X", 48879), "0xBEEF");
    assert_eq!(format_num!(".2s", 42e6), "42M");
    assert_eq!(format_num!(".^20d", 12), ".........12........."); // dot filled and centered
    assert_eq!(format_num!("+10.0f", 255), "      +255");
    assert_eq!(format_num!(".0%", 0.123), "12%");
    assert_eq!(format_num!("+016,.2s", 42e12), "+000,000,000,042T"); // grouped zero-padded with a mandatory sign, SI-prefixed with 2 significant digits
}

注意

当前的一个限制是,要格式化的数字应该实现Into<f64>,对于大于u64::MAX的数字,可能会丢失一些精度。

路线图

更多类型的实现:g(通用格式)、n(数字)、c(字符)。

此外,还计划添加对区域设置和货币格式的支持。

许可证

format_num根据您的选择,受Apache License,版本2.0MIT许可证的许可。

依赖项

~2.2–3MB
~54K SLoC