#fixed-point #numbers #typenum #no-std

no-std ufix

灵活且可用的泛型定点数值类型

1个不稳定版本

0.1.0 2020年7月13日

#437嵌入式开发

MIT 协议

55KB
1K SLoC

灵活的定点数

此crate旨在简化固定点类型的使用,尤其是在无FPU硬件上。为此,它引入了具有可使用和灵活操作的泛型固定点类型。

概述

引入的数值类型是具有三个类型参数的泛型

  • Radix - 类型的基础,2表示二进制小数点,10表示十进制小数点
  • Digits - 有价值数字的数量,代表**尾数**
  • Exponent - 类型的静态**指数**值

因此,类型的值可以表示为 mantissa × radix exponent

# use ufix::{Fix, bin, dec};
# use typenum::*;
#
// Signed binary fixed with 5 bits mantissa and -3 as exponent.
// [5]*2^-3
type BF1 = Fix<P2, P5, N3>;
// or using type alias
type BF2 = bin::Fix<P5, N3>;

// Unsigned binary fixed with 5 bits mantissa and 3 as exponent.
// [5]*2^3
type BF1 = Fix<U2, P5, P3>;
// or using type alias
type BF2 = bin::UFix<P5, P3>;

// Signed decimal fixed with 12 digits mantissa and -7 as exponent.
// [12]*10^-7
type DF1 = Fix<P12, U10, N7>;
type DF2 = dec::Fix<P12, N7>;

P* 作为基数类型参数表示有符号类型。要创建无符号类型,请使用 U* 代替。

与众所周知且广泛使用的 Qn.m 表示法不同,指数不受尾数位的限制。它可以小于尾数位以表示更精确的小值。此外,它也可以大于零以表示精度较低的大值。

# use ufix::Fix;
# use typenum::*;
#
// [5]*2^-7
// 0b0.0000000 .. 0b0.0011111
type BF1 = Fix<U2, U5, N7>;

// [5]*2^7
// 0b0000000 .. 0b1111100
type BF2 = Fix<U2, U5, P7>;

定点算术在乘法中存在众所周知的溢出问题,特别是在无FPU硬件上。此外,它在除法中存在众所周知的精度损失问题。

此crate通过根据特定操作调整尾数宽度和指数值来避免溢出和精度损失。

请参阅下面的示例

use ufix::{Cast, bin::{Fix}};
use typenum::*;

let a = Fix::<P16, N8>::from(123.45);
let b = Fix::<P12, N6>::from(78.9);

// The addition without overflow
let c = a + b; // Fix<P17, N8>

assert_eq!(c, Fix::<P17, N8>::from(202.34));
use ufix::{Cast, bin::{Fix}};
use typenum::*;

let a = Fix::<P16, N8>::from(123.45);
let b = Fix::<P16, N8>::from(78.9);

// The multiplication without overflow
let c = a * b; // Fix<P32, N16>

assert_eq!(c, Fix::<P32, N16>::from(9739.95047));
use ufix::{Cast, bin::{Fix}};
use typenum::*;

let a = Fix::<P16, N8>::from(123.45);
let b = Fix::<P16, N8>::from(78.9);

// The division without precision loss
let c = Fix::<P32, N16>::cast(a) / b;

assert_eq!(c, Fix::<P16, N8>::from(1.5647));

优化技术

当您针对 FPU 无硬件以获得最佳性能并减小固件大小时,应仅使用二进制定点算术,因为内部它使用整数操作,并且指数调整操作只需要位操作。此外,当可能且不损失所需精度时,应避免超过平台字大小。

默认情况下,此crate使用32位整数作为在32位处理器上使用的最佳选择。当您针对16位或8位处理器时,通常应分别使用 _word16 或 _word8 功能。

支持的功能

此crate按设计是 no_std

此crate支持高达 64位 的尾数。使用 i128 功能可以启用高达 128位 的支持。

word8word16 功能可以将最小尾数大小分别减少到8位和16位。默认情况下,至少使用32位字。

Fix 类型的演变

  1. Curtis McEnroe 创建的 fix 包。

    该包定义了一个简单的定点类型,支持泛型 基数指数。这项工作是从 fix 的继承者开始的。

  2. Bits 参数的意义从 尾数类型 更改为 尾数位数

    为了获得更多定点类型的灵活性,我们需要知道尾数的有效位数。这样我们就可以轻松地选择操作结果的适当类型。此外,这也使得可以操作具有不同尾数和指数的操作数。

  3. Bits 参数的意义从 尾数位数 更改为 根据基数计算的尾数位数

    实际上,与数字的实际位数相比,使用二进制位数进行操作更为简单。因为位数取决于基数,所以对于二进制定点类型,它仍然是与之前相同的位数。

依赖项

~180KB