3 个稳定版本

1.1.1 2023年7月14日
1.1.0 2023年7月9日
1.0.0 2023年1月18日

国际化 (i18n) 中排名 30

Download history 572/week @ 2024-03-13 498/week @ 2024-03-20 526/week @ 2024-03-27 531/week @ 2024-04-03 404/week @ 2024-04-10 418/week @ 2024-04-17 448/week @ 2024-04-24 488/week @ 2024-05-01 650/week @ 2024-05-08 551/week @ 2024-05-15 464/week @ 2024-05-22 574/week @ 2024-05-29 541/week @ 2024-06-05 552/week @ 2024-06-12 501/week @ 2024-06-19 437/week @ 2024-06-26

每月下载量 2,114
19 Crates 中使用(直接使用 4 个)

MIT 许可证

68KB
1K SLoC

快速且友好的 Rust 数字格式化。

格式化数字。

提供用于使用各种方法格式化十进制数字的 Formatter。格式化注重性能,通常比 std 更快,功能更丰富。还有一个可以按照特定语法使用字符串来定义 Formatter字符串解析器

过程

格式化通过遵循以下程序的 Formatter::fmt 来完成:

  1. 使用定义的 Scales 缩放数字,
  2. 检查缩放后的数字是否超过或低于 科学记数法截止值
  3. 添加定义的千位分隔符,
  4. 在定义的 Precision 处停止,
  5. 应用有效的前缀、后缀和单位装饰。

用法

默认用法

Default::default 提供一个具有以下属性的通用默认格式化器

# use numfmt::*;
let mut f = Formatter::default();
assert_eq!(f.fmt(0.0), "0");
assert_eq!(f.fmt(12345.6789), "12.345 K");
assert_eq!(f.fmt(0.00012345), "1.234e-4");
assert_eq!(f.fmt(123456e22), "1,234.559 Y");

自定义用法

Formatter 提供许多不同的选项来自定义数字的格式化方式。以下示例显示了如何开发货币格式

# use numfmt::*;
let mut f = Formatter::new() // start with blank representation
    .separator(',').unwrap()
    .prefix("AU$").unwrap()
    .precision(Precision::Decimals(2));

assert_eq!(f.fmt(0.52), "AU$0.52");
assert_eq!(f.fmt(1234.567), "AU$1,234.56");
assert_eq!(f.fmt(12345678900.0), "AU$12,345,678,900.0");

科学记数法

当缩放后的数字大于 12 位整数数字(123,456,789,000)或小于 3 位前导零(0.0001234)时,将启动科学记数法。数字 始终 有一个前导整数数字,默认为 7 位有效数字

精度

可以通过Precision指定精度,无论是小数位数还是有效数字。

# use numfmt::*;
let mut f = Formatter::new();
assert_eq!(f.fmt(1234.56789), "1234.56789");

f = f.precision(Precision::Decimals(2));
assert_eq!(f.fmt(1234.56789), "1234.56");

f = f.precision(Precision::Significance(5));
assert_eq!(f.fmt(1234.56789), "1234.5");

性能

格式化通常比stdf64::to_string实现要快。当构造一个Formatter时,会有一个缓冲区的分配,以及任何缩放的分配。建议重用Formatter以避免不必要的分配。在cached行中显示了重用格式化器后的更好性能。

时间(纳秒) 0.0 0.1234 2.718281828459045 1.797693148623157e307
numfmt - 默认 35 115 153 195
numfmt - 缓存 2 75 89 126
std 35 96 105 214

示例 - 文件大小格式化器

通过组合缩放、后缀和精度,可以构建一个文件大小打印机。

# use numfmt::*;
let mut f = Formatter::new()
                .scales(Scales::binary())
                .precision(Precision::Significance(3))
                .suffix("B").unwrap();

assert_eq!(f.fmt(123_f64), "123 B");
assert_eq!(f.fmt(1234_f64), "1.20 kiB");
assert_eq!(f.fmt(1_048_576_f64), "1.0 MiB");
assert_eq!(f.fmt(123456789876543_f64), "112 TiB");

解析

定义了一个语法,可以将数据解析为Formatter。这种字符串表示可以用于格式化数字的用户输入。语法由一个前缀、括号内的数字格式和一个后缀定义。

prefix[[.#|~#|.*][%|s|b|n][/<char>]]suffix
^----^ ^--------^^-------^^-------^ ^----^
prefix precision scale    separator suffix

每个组件都是可选的,包括数字格式。所有格式都应用于默认Formatter,因此空格式将导致默认的格式化器

前缀和后缀

前缀和后缀绑定到支持的长度,并且可以包含任何字符。要使用[]字符,必须使用双括号。

示例

# use numfmt::*;
let mut f: Formatter;
f = "".parse().unwrap();
assert_eq!(f.fmt(1.234), "1.234");

f = "prefix ".parse().unwrap();
assert_eq!(f.fmt(1.234), "prefix 1.234");

f = "[] suffix".parse().unwrap();
assert_eq!(f.fmt(1.234), "1.234 suffix");

f = "[[prefix [] suffix]]".parse().unwrap();
assert_eq!(f.fmt(1.234), "[prefix 1.234 suffix]");

精度

使用点.定义小数精度,或使用~定义有效数字精度,后跟一个数字。支持的最多为255。有一个特殊情况:.*移除任何默认精度并使用Precision::Unspecified

示例

# use numfmt::*;
let mut f: Formatter;
f = "[.2]".parse().unwrap(); // use two decimal places
assert_eq!(f.fmt(1.2345), "1.23");

f = "[.0]".parse().unwrap(); // use zero decimal places
assert_eq!(f.fmt(10.234), "10");

f = "[.*]".parse().unwrap(); // arbitary precision
assert_eq!(f.fmt(1.234), "1.234");
assert_eq!(f.fmt(12.2), "12.2");

f = "[~3]".parse().unwrap(); // 3 significant figures
assert_eq!(f.fmt(1.234), "1.23");
assert_eq!(f.fmt(10.234), "10.2");

缩放

缩放使用一个字符来表示应该使用哪种缩放。默认情况下使用SI缩放。以下字符被支持

示例

# use numfmt::*;
let mut f: Formatter;
f = "".parse().unwrap(); // default si scaling used
assert_eq!(f.fmt(12345.0), "12.345 K");

f = "[n]".parse().unwrap(); // turn off scaling
assert_eq!(f.fmt(12345.0), "12,345.0");

f = "[%.2]".parse().unwrap(); // format as percentages with 2 decimal places
assert_eq!(f.fmt(0.234), "23.40%");

f = "[b]".parse().unwrap(); // use a binary scaler
assert_eq!(f.fmt(3.14 * 1024.0 * 1024.0), "3.14 Mi");

分隔符

可以通过使用一个跟随字符的斜杠/来指定一个分隔符字符。解析器使用下一个字符字面量,除非该字符是],在这种情况下,分隔符被设置为None。默认分隔符是逗号。

示例

# use numfmt::*;
let mut f: Formatter;
f = "[n]".parse().unwrap(); // turn off scaling to see separator
assert_eq!(f.fmt(12345.0), "12,345.0");

f = "[n/]".parse().unwrap(); // use no separator
assert_eq!(f.fmt(12345.0), "12345.0");

f = "[n/.]".parse().unwrap(); // use a period
assert_eq!(f.fmt(12345.0), "12.345.0");

f = "[n/_]".parse().unwrap(); // use a underscroll
assert_eq!(f.fmt(12345.0), "12_345.0");

f = "[n/ ]".parse().unwrap(); // use a space
assert_eq!(f.fmt(12345.0), "12 345.0");

组合格式

已经有一些关于格式组合的例子了。必须遵守 prefix[num]suffix 的顺序,但数字格式内的排序是任意的。建议保持与 精度、缩放、分隔符 的一致性,这有助于提高可读性并降低格式错误(在解析阶段将产生错误)的风险。

各种组合示例

# use numfmt::*;
let mut f: Formatter;

// Percentages to two decimal places
f = "[.2%]".parse().unwrap();
assert_eq!(f.fmt(0.012345), "1.23%");

// Currency to zero decimal places
// notice the `n` for no scaling
f = "$[.0n] USD".parse().unwrap();
assert_eq!(f.fmt(123_456_789.12345), "$123,456,789 USD");

// Formatting file sizes
f = "[~3b]B".parse().unwrap();
assert_eq!(f.fmt(123_456_789.0), "117 MiB");

// Units to 1 decimal place
f = "[.1n] m/s".parse().unwrap();
assert_eq!(f.fmt(12345.68), "12,345.6 m/s");

依赖项

~52KB