如何从具有整数和分数的任意拆分的原始整数类型解析二进制补码定点数?
How do I parse a two's-complement fixed-point number from a primitive integer type with an arbitrary split of integer and fraction?
我正在解析 OpenType 字体文件,需要解析(和写入)两种定点数:
- 16 位有符号固定数,小数 (2.14) 的低 14 位
- 32 位有符号定点数 (16.16)
我假设,最后,它应该被投射to/from f32
The F2DOT14 format consists of a signed, 2’s complement integer and an
unsigned fraction. To compute the actual value, take the integer and
add the fraction.
2.14 值的示例是:
Decimal Value Hex Value Integer Fraction
1.999939 0x7fff 1 16383/16384
1.75 0x7000 1 12288/16384
0.000061 0x0001 0 1/16384
0.0 0x0000 0 0/16384
-0.000061 0xffff -1 16383/16384
-2.0 0x8000 -2 0/16384
我有一个有效的解决方案,但仅适用于 2.14 值:
fn from(number: u16) -> f32 {
let mut int = (number >> 14) as f32;
if int > 1f32 {
int -= 4f32;
}
let frac = (number & 0b11_1111_1111_1111) as f32 / 16384 as f32;
int + frac
}
因为整数值应该是[-2, 2), 我解析出来的整数大于1就减4得到负数
我正在寻找一种方法来对定点数进行任何可能的拆分(例如 2.14
、16.16
、3.5
、24.40
、等)在 Rust 整数原始类型的标准范围内(u16
、u32
、u64
等)。
能够解决我的问题,这里是一个解析 16 位定点数的例子:
use std::mem::size_of;
fn from_u16(raw: u16, frac_count: usize) -> f32 {
let bit_count = size_of::<u16>() * 8;
let int_count = bit_count - frac_count;
let unsigned = (raw >> frac_count) as isize;
let sign_bit = unsigned >> (int_count - 1) & 1;
let high_bits = if sign_bit == 1 { -1 } else { 0 };
let signed = high_bits << int_count | unsigned as isize;
let mut mask = 0;
for i in 0..=frac_count {
mask = mask << i | 1;
}
let frac = (raw & mask) as f32 / (1 << frac_count) as f32;
signed as f32 + frac
}
我正在解析 OpenType 字体文件,需要解析(和写入)两种定点数:
- 16 位有符号固定数,小数 (2.14) 的低 14 位
- 32 位有符号定点数 (16.16)
我假设,最后,它应该被投射to/from f32
The F2DOT14 format consists of a signed, 2’s complement integer and an unsigned fraction. To compute the actual value, take the integer and add the fraction.
2.14 值的示例是:
Decimal Value Hex Value Integer Fraction
1.999939 0x7fff 1 16383/16384
1.75 0x7000 1 12288/16384
0.000061 0x0001 0 1/16384
0.0 0x0000 0 0/16384
-0.000061 0xffff -1 16383/16384
-2.0 0x8000 -2 0/16384
我有一个有效的解决方案,但仅适用于 2.14 值:
fn from(number: u16) -> f32 {
let mut int = (number >> 14) as f32;
if int > 1f32 {
int -= 4f32;
}
let frac = (number & 0b11_1111_1111_1111) as f32 / 16384 as f32;
int + frac
}
因为整数值应该是[-2, 2), 我解析出来的整数大于1就减4得到负数
我正在寻找一种方法来对定点数进行任何可能的拆分(例如 2.14
、16.16
、3.5
、24.40
、等)在 Rust 整数原始类型的标准范围内(u16
、u32
、u64
等)。
能够解决我的问题,这里是一个解析 16 位定点数的例子:
use std::mem::size_of;
fn from_u16(raw: u16, frac_count: usize) -> f32 {
let bit_count = size_of::<u16>() * 8;
let int_count = bit_count - frac_count;
let unsigned = (raw >> frac_count) as isize;
let sign_bit = unsigned >> (int_count - 1) & 1;
let high_bits = if sign_bit == 1 { -1 } else { 0 };
let signed = high_bits << int_count | unsigned as isize;
let mut mask = 0;
for i in 0..=frac_count {
mask = mask << i | 1;
}
let frac = (raw & mask) as f32 / (1 << frac_count) as f32;
signed as f32 + frac
}