13 个版本 (破坏性)
0.11.0 | 2024年3月6日 |
---|---|
0.10.0 | 2023年11月23日 |
0.9.1 | 2023年10月25日 |
0.8.0 | 2023年7月23日 |
0.1.0 | 2022年7月10日 |
#45 in 加密学
60,283 每月下载量
用于 646 个crate(直接使用4个)
440KB
10K SLoC
bnum
Rust的任意精度、固定大小的有符号和无符号整数类型。
概述
此crate的目标是提供与Rust原生整数类型(如u8
、i8
、u16
、i16
等)完全相同的整数类型:几乎所有在Rust的有符号和无符号原生整数上定义的方法都在bnum
的有符号和无符号整数上定义。此外,还提供了一些其他有用的方法,大部分灵感来自BigInt
和BigUint
类型,这些类型来自num_bigint
crate。
此crate使用Rust的const generics来允许创建在编译时可以确定的任意大小的整数。无符号整数存储为长度为N
的数字数组(原生无符号整数)。这意味着所有bnum
整数都可以存储在栈上,因为它们是固定大小的。有符号整数简单地存储为二进制补码形式的无符号整数。
bnum
定义了 4 种无符号整数类型:每种类型使用不同的原始整数类型作为其数字类型。 BUint
使用 u64
作为其数字类型,BUintD32
使用 u32
,BUintD16
使用 u16
,而 BUintD8
使用 u8
。有符号整数类型 BInt
、BIntD32
、BIntD16
和 BIntD8
分别由这些无符号整数表示。
BUint
和 BInt
由于存储(并且因此操作)给定位数大小的最少数字,所以速度最快。然而,缺点是位数大小必须是 64
的倍数(bitsize = N * 64
)。这就是为什么还提供了其他整数类型,因为它们允许位数大小是 32
、16
或 8
的倍数。在选择使用哪种类型时,确定 64, 32, 16, 8
中的哪一个是最大除数,并使用相应的类型。例如,如果您想有一个 96 位的无符号整数,32 是这些中 96 的最大除数,所以使用 BUintD32<3>
。一个 40 位的有符号整数将是 BIntD8<5>
。
为什么是 bnum?
- 默认无依赖:默认情况下,
bnum
不依赖于任何其他 crate。可以通过 crate features 启用对rand
和serde
等crate 的支持。 no-std
兼容:如果未启用arbitrary
和quickcheck
功能,则bnum
可以在no_std
环境中使用。- 编译时整数解析:在
bnum
整数上的from_str_radix
和parse_str_radix
方法是const
,这使得可以在编译时解析来自字符串切片的整数。请注意,这比编译时解析整数文字更强大。这是因为它允许解析从2
到36
的所有基数(包括2
、8
、10
和16
)。此外,要解析的字符串不一定是文字:例如,它可以通过include_str!
或env!
` 获取。 const
评估:在bnum
整数上定义的几乎所有方法都是const
,这允许复杂的编译时计算。
安装
要安装和使用bnum
,只需将以下行添加到您的Cargo.toml
文件中的[dependencies]
部分
bnum = "0.11.0"
或者,为了启用bnum
的各种功能,例如,添加以下行代替
bnum = { version = "0.11.0", features = ["rand"] } # enables the "rand" feature
示例用法
注意:文档中的示例使用特定的类型别名(例如U256
、U512
或I256
、I512
)来给出大多数方法的正确使用示例。这些类型并没有什么特殊之处:所有使用这些类型展示的方法都为任何值N
的所有无符号/有符号bnum
整数实现了。
// As of version 0.6.0, you can parse integers from string slices at compile time with the const methods `from_str_radix` or `parse_str_radix`:
use bnum::types::{U256, I256};
use bnum::errors::ParseIntError;
// `parse_str_radix` returns an integer, and panics if the string fails to parse
const UINT_FROM_DECIMAL_STR: U256 = U256::parse_str_radix("12345678901234567890", 10);
// If you are not sure that the string will successfully parse, you can use `from_str_radix` which returns a `Result`
const RESULT_INT_FROM_HEXA_STR: Result<I256, ParseIntError> = I256::from_str_radix("-1234567890abcdef", 16);
assert_eq!(format!("{}", UINT_FROM_DECIMAL_STR), "12345678901234567890");
assert_eq!(format!("{:x}", RESULT_INT_FROM_HEXA_STR.unwrap().abs()), "1234567890abcdef");
// Calculate the `n`th Fibonacci number, using the type alias `U512`.
use bnum::types::U512; // `U512` is a type alias for a `BUint` which contains 8 `u64` digits
// Calculate the nth Fibonacci number
fn fibonacci(n: usize) -> U512 {
let mut f_n: U512 = U512::ZERO; // or `U512::from(0u8)`
let mut f_n_next: U512 = U512::ONE; // or `U512::from(1u8)`
for _ in 0..n {
let temp = f_n_next;
f_n_next += f_n;
f_n = temp;
}
f_n
}
let n = 100;
let f_n = fibonacci(n);
println!("The {}th Fibonacci number is {}", n, f_n);
// Prints "The 100th Fibonacci number is 354224848179261915075"
assert_eq!(f_n, U512::from_str_radix("354224848179261915075", 10).unwrap());
// Construct an 80-bit signed integer
// Out of [64, 32, 16, 8], 16 is the largest divisor of 80, so use `BIntD16`
use bnum::BIntD16;
type I80 = BIntD16<5>; // 80 / 16 = 5
let neg_one = I80::NEG_ONE; // -1
assert_eq!(neg_one.count_ones(), 80); // signed integers are stored in two's complement so `-1` is represented as `111111...`
功能
模糊测试
arbitrary
功能从arbitrary
存储库中推导出Arbitrary
特质。**注意:目前,此功能无法与no_std
一起使用(请参阅https://github.com/rust-fuzz/arbitrary/issues/38
)**。
随机数生成
rand
功能允许通过rand
存储库创建随机bnum
整数。
序列化和反序列化
serde
功能通过serde
和serde_big_array
存储库启用bnum
整数的序列化和反序列化。
num_traits
和num_integer
特质实现
numtraits
功能包括来自num_traits
和num_integer
存储库的特质的实现,例如AsPrimitive
、Signed
、Integer
和Roots
。
Quickcheck
quickcheck
功能启用quickcheck
存储库中的Arbitrary
特质。**注意:目前,此功能无法与no_std
一起使用**。
Zeroize
zeroize
功能启用zeroize
存储库中的Zeroize
特质。
Valuable
valuable
功能启用valuable
存储库中的Valuable
特质。
夜间功能
激活 nightly
功能将启用 from_be_bytes
、from_le_bytes
、from_ne_bytes
、to_be_bytes
、to_le_bytes
和 to_ne_bytes
方法,这些方法作用于 bnum
的无符号和有符号整数,并将 unchecked_...
方法标记为 const
。但这样做代价是只能编译在 nightly 版本上。这个功能使用的 nightly 特性包括:generic_const_exprs
、const_trait_impl
和 const_option_ext
。
测试
此软件包使用 quickcheck
软件包以及特定的边缘情况进行测试。将方法输出与原始整数的等效方法输出进行比较,以确保行为相同。
最低支持的 Rust 版本
当前最低支持的 Rust 版本 (MSRV) 为 1.65.0
。
文档
如果一个方法没有明确文档,它将链接到原始 Rust 整数上定义的等效方法(因为它们具有相同的功能)。
注意:bnum
目前处于预 1.0.0
阶段。根据 语义版本控制指南,在此阶段,公共 API 可能包含破坏性更改。然而,由于 API 设计尽可能类似于 Rust 原始整数的 API,因此不太可能出现大量的破坏性更改。
已知问题
目前,对于 bnum
整数实现了 From
特性,从所有 Rust 原始整数。然而,这种行为并不完全正确。例如,如果创建了一个 24 位宽的无符号整数(BUintD8<3>
),则不应实现 From<u32>
等,而应实现 TryFrom<u32>
。为确保正确的行为,可以使用来自 num_traits
软件包的 FromPrimitive
特性,因为这总会返回一个 Option
而不是整数本身。
num_traits::NumCast
特性为 bnum
整数实现了,但如果调用其方法 from
,则会故意触发 panic,因为这无法保证正确的转换,因为 NumCast
特性强制执行了约束。因此,不应在 bnum
整数上使用此特性。此实现的唯一目的是允许实现 num_traits::PrimInt
特性。
以前的错误
以前版本中的错误列表可以在 changes/prior-bugs.md
找到。
未来工作
此库旨在提供 Rust 的 3 种内置数字类型的任意精度和固定精度等效项:有符号整数、无符号整数和浮点数。有符号和无符号整数已实现并经过全面测试,并力求与 Rust 的整数接口保持同步。(例如,当在 Rust 原始整数上实现新方法时,此库将努力同步,包括该方法。这包括仅限夜间的功能。)
目前,正在开发任意精度固定大小浮点数,但尚不完整。大多数基本方法,如算术和分类,已实现,但截至目前,尚未实现如 sin
、exp
、log
等超越浮点数方法。
此外,还将在某个时候开发用于解析数字值的 proc 模块。
许可
bnum
许可证为 MIT 许可证或 Apache 许可证 2.0。
依赖项
~0–500KB