#numbers #variables #integer #overflow #operations #primitive #length

var_num

可变长度的数字实现,可以作为任何数字原语的直接替换

12个不稳定版本 (3个破坏性)

0.4.2 2024年7月17日
0.4.1 2024年7月15日
0.3.0 2024年7月15日
0.2.4 2024年7月13日
0.1.2 2024年7月10日

#232 in 数学

Download history 134/week @ 2024-06-28 151/week @ 2024-07-05 656/week @ 2024-07-12 50/week @ 2024-07-19 114/week @ 2024-07-26 8/week @ 2024-08-02

890 每月下载量
用于 3 个crates (2 直接)

MIT 许可证

51KB
1.5K SLoC

var_num

这个crate的想法受到了Rob Pike的“我们做对了什么,我们做错了什么”演讲的启发,他提到int类型应该是可变长度的,“如果它们不会溢出”。这个crate是为了被rigz_vm/fn_vm使用,以简化数字处理。

可变长度数字实现,可以作为任何数字原语的直接替换,值最初以最小的表示形式存储(当调用From时)。对于数学运算,输出值与左侧的操作数的整体类型匹配。假设以下内容首先转换为值

i32::MAX - i16::MAX = i16
f32::MAX + u8::MAX = f32 // overflow, TODO #1

组件

以下枚举不应直接创建,而应使用From trait转换为所需类型。

  • VarNum:主要类型,用于存储数字并表示任何数字。
  • VarFloat:可以用于存储任何浮点数的浮点类型。
  • VarInt:可以用于存储任何整数的有符号整数类型,支持自动溢出和下溢。
  • VarUInt:可以用于存储任何无符号整数的无符号整数类型。

用法

use var_num::VarNum;

fn main() {
    let a: u8 = 255;
    let b: f32 = 3.14;
    let a: VarNum = a.into();
    let b: VarNum = b.into();
    let num = a + b;
    // num is a VarNum::U16(258)
    let num = b + a;
    // num is a VarNum::F32(258.14)
}

特殊案例

Float和UInt保持不变,但它们包含所有int上可用的操作。对于int,这个crate使用checked_*来处理溢出或下溢,带有一些短路以跳过操作。

BitAnd、BitOr、BitXor、Shl和Shr运算符保持不变,并且不会改变值的尺寸。对于前三个运算符,值的尺寸不能改变,并且没有其他特殊情况;对于最后两个,我个人不希望我的数字在移位时改变大小(即使是int,这可能在未来的版本中改变)。

待办事项

  • 在需要时自动从f32扩展到f64,为Float实现checked_*。
  • 允许通过scaled_*函数扩展UInt,而不是默认行为
  • 允许对Shl或Shr进行显式缩放,包括scaled_shl和scaled_shr
  • 通过功能添加对夜间自定义类型的支持
  • 基准测试(从,操作,到/从字节等。)

依赖关系

~1.2–1.8MB
~32K SLoC