2 个版本

0.1.1 2020 年 1 月 19 日
0.1.0 2020 年 1 月 19 日

#903算法

Download history 144/week @ 2024-04-07 109/week @ 2024-04-14 94/week @ 2024-04-21 92/week @ 2024-04-28 89/week @ 2024-05-05 93/week @ 2024-05-12 138/week @ 2024-05-19 122/week @ 2024-05-26 302/week @ 2024-06-02 278/week @ 2024-06-09 120/week @ 2024-06-16 126/week @ 2024-06-23 420/week @ 2024-06-30 202/week @ 2024-07-07 270/week @ 2024-07-14 282/week @ 2024-07-21

每月 1,176 次下载
3 个crate中使用了(通过 giga-segy-core

BSD-3-Clause

57KB
1K SLoC

ibmfloat

A Rust 库,用于处理 IBM 浮点数,特别关注将其转换为 IEEE-754 浮点值。

这个crate没有Rust依赖,没有C依赖,并且没有 unsafe 代码。它的 std 功能默认启用,可以通过禁用来支持 #![no_std] 环境。

转换过程和大部分测试套件来自 Python ibm2ieee

性能

笔记本电脑的代表性结果

F32 to f32              time:   [6.7092 ns 6.7734 ns 6.8454 ns]                        
F32 to f64              time:   [2.4642 ns 2.4965 ns 2.5326 ns]                        
F64 to f32              time:   [7.2500 ns 7.3315 ns 7.4169 ns]                        
F64 to f64              time:   [2.7761 ns 2.8028 ns 2.8342 ns]                        

转换为 f32 的开销比转换为 f64 要高。

用法

32位浮点数

ibmfloat::F32 表示一个32位IBM浮点数。它支持以下转换

  • 通过 from_bits()to_bits() 将其转换为/从 u32
  • 通过 from_be_bytes()/to_be_bytes() 将其转换为/从大端 [u8; 4]
  • 通过 From/Into 损失性地转换为 f32
  • 通过 From/Into 无损性地转换为 f64

IBM F32 单精度浮点数比 IEEE-754 f32 单精度浮点数的精度略低,但其覆盖的范围略大。典型大小的 F32 可以转换为 f32 而不会出现舍入或其他精度损失。将大范围的 F32 转换为 f32 将导致舍入;极大幅度的 F32 也可能导致溢出和下溢。

每个 F32 都可以精确地表示为一个 f64,不会出现舍入、溢出或下溢。那些寻求无损路径到 IEEE-754 的人应该将 F32 转换为 f64

// Use the example -118.625:
//   https://en.wikipedia.org/wiki/IBM_hexadecimal_floating_point#Example
let foreign_float = ibmfloat::F32::from_bits(0b1_1000010_0111_0110_1010_0000_0000_0000);

let native_float = f32::from(foreign_float);
assert_eq!(native_float, -118.625f32);

let native_float: f32 = foreign_float.into();
assert_eq!(native_float, -118.625f32);

64位浮点数

ibmfloat::64 表示一个 64 位 IBM 浮点数。它支持以下转换

  • 通过 from_bits()to_bits() 将其转换为/从 u64
  • 通过 from_be_bytes()/to_be_bytes() 将其转换为/从大端 [u8; 8]
  • 通过 From/Into 损失性地转换为 f32
  • 通过 From/Into 无损地将其转换为 f64

IBM F64 浮点数的精度略高于 IEEE-754 f64 浮点数,但它们的覆盖范围略小。大多数转换将需要舍入,但不会出现溢出或下溢的风险。

let foreign_float = ibmfloat::F64::from_bits(0x4110000000000000);

let native_float = f64::from(foreign_float);
assert_eq!(native_float, 1.0f64);

let native_float: f64 = foreign_float.into();
assert_eq!(native_float, 1.0f64);

开发

请使用 cargo testcargo clippycargo fmt 逐步进行。请还使用 cargo test --no-default-features 以防止意外破坏 #![no_std] 用户。GitHub Actions 在推送时运行这些命令。

ibm2ieee-sys/ 包含一个封装 ibm2ieee.c 的 crate,测试比较 ibm2ieee.c 对随机值的转换与 ibmfloat 的转换,以及两个库的基准测试。

$ cd ibm2ieee-sys/
$ cargo test
$ cargo bench

cargo fuzz 覆盖了四个 IBM 到 IEEE 转换路径,并将它们与 ibm2ieee-sys 进行比较。如果您对该逻辑进行修改,请按需运行它们。

$ cargo +nightly fuzz run ibm32ieee32
$ cargo +nightly fuzz run ibm32ieee64
$ cargo +nightly fuzz run ibm64ieee32
$ cargo +nightly fuzz run ibm64ieee64

其他参考

无运行时依赖

特性