rust - 如何从具有整数和分数的任意拆分的原始整数类型解析二进制补码定点数?
问题描述
我正在解析 OpenType 字体文件,需要解析(和写入)两种定点数:
- 带小数低 14 位的 16 位有符号固定数 (2.14)
- 32 位有符号定点数 (16.16)
我认为,最后,它应该被投向/从f32
OpenType 规范描述:
F2DOT14 格式由一个带符号的 2 的补码整数和一个无符号小数组成。要计算实际值,请取整数并加上分数。
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,得到负数。
我正在寻找一种方法来在Rust 整数原始类型( 、、等)的标准范围内对定点数(如2.14
、16.16
、3.5
、等)进行任何可能的拆分。24.40
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
}
推荐阅读
- c++ - 为什么这个面向对象的 OpenGL 代码不会绘制一个三角形,而扩展版本却可以呢?
- go - 在 Redis DB 中保存 1000 万条记录的瓶颈
- react-native - 反应原生分页
- python - 如何在 tkinter 中隐藏带有复选框的小部件
- android - 在 Activity 中检索协程广播消息时出现问题
- flutter - 视频无法在颤振 Web 应用程序中播放
- asp.net-core - Asp.net Core 5 .well-known 提供 default.json 文件
- python - sqlite sqlalchemy“IndexError:列表索引超出范围”
- oauth2-playground - Google 令牌已过期或撤销:invalid_grant
- java - 复合模型中的火属性变化