1 个不稳定版本
0.2.1 | 2022年3月4日 |
---|
#2290 在 Rust 模式
21KB
414 行
hexf
为 Rust 1.43 或更高版本提供十六进制浮点数支持。(对于更早版本,请尝试 0.1.0
)
use hexf::hexf64;
assert_eq!(hexf64!("0x1.999999999999ap-4"), 0.1f64);
字面量具有显式类型,应与以下模式匹配:SIGN "0x" INTEGRAL "." FRACTIONAL "p" EXPSIGN EXPDIGITS
,其中
-
所有拉丁字母均不区分大小写进行匹配;
-
SIGN
和EXPSIGN
可以为+
、-
或空; -
INTEGRAL
和FRACTIONAL
是一个或多个十六进制数字,可选地由或以一个下划线(_
)分隔(但不能以它开始); -
INTEGRAL
或FRACTIONAL
至少应有一个存在(允许1.0
或.0
或1.
,但不允许1
); -
EXPDIGITS
是十进制数字,可选地由或以一个下划线(_
)分隔或开始或结束。
将无效字面量放入是编译时错误。
// hexf32! failed: invalid hexadecimal float literal
let invalid = hexf32!("42");
将无法在目标类型中精确表示的字面量放入也是编译时错误。
// hexf32! failed: cannot exactly represent float in target type
let inexact = hexf32!("0x1.99999bp-4");
// hexf32! failed: cannot exactly represent float in target type
let inexact_subnormal = hexf32!("0x1.8p-149");
// hexf64! failed: cannot exactly represent float in target type
let overflow = hexf64!("0x1.0p1024");
// hexf64! failed: cannot exactly represent float in target type
let underflow = hexf64!("0x1.0p-1075");
该软件包(以及独立的 hexf-parse
软件包)提供了 parse_hexf32
和 parse_hexf64
函数,允许解析失败(通过 ParseHexfError
类型报告)。这些函数将仅在第二个参数为 true 时允许交错下划线;这是为了保持一致性,因为 Rust 允许在数字字面量中使用下划线,但在标准库中不允许("3_4".parse::<i32>()
是错误)。
它是如何工作的?
这个crate高度依赖于最近的Rust编译器能够正确地打印和读取浮点数。因此,这个crate的实际实现是通过将解析后的十六进制浮点数打印回正确的十进制数字,然后由编译器选择来产生一个精确的位模式。
等等,十六进制浮点数有什么意义?答案是,它们是ISO C99“发明”的,以避免实现陷阱。理想情况下,应该能够枚举足够多的分数位来得到正确舍入的位模式,但许多实现并没有做到(这在很大程度上是可以理解的,因为实际上相当困难)。因此,标准做出了妥协:在符合标准的实现中,十进制浮点数应该解析得非常接近,但不完全等于正确的舍入数。
尾数部分被解释为一个(十进制或十六进制)有理数;指数部分的数字序列被解释为一个十进制整数。[...] 对于十进制浮点常量,以及在FLT_RADIX不是2的幂的情况下,十六进制浮点常量,结果要么是最近的表示值,要么是紧邻最近表示值的大或小表示值,以实现定义的方式选择。[...]
——ISO C99,第6.4.4.2节 浮点常量,第3段(加粗部分是我强调的)
事实上,在这个精度下解析十进制浮点数相对容易。十六进制浮点数就是从这种传统中产生的,但Rust不必这样!十六进制浮点数仍然可以用于手动编写浮点数位,或用于从其他语言转换,然而。这个crate就是为了那些罕见的使用情况而存在的。
更多上下文请参阅rust-lang/rust#1433。
依赖项
~410KB