39 lines
1.3 KiB
Rust
39 lines
1.3 KiB
Rust
|
pub fn encode_float(f: f32) -> (i32, i32) {
|
||
|
let bits = f.to_bits();
|
||
|
let mantissa = (bits & 0x007FFFFF) as i32;
|
||
|
let exponent = ((bits >> 23) & 0xFF) as i32;
|
||
|
let sign = if f < 0.0 { 1 } else { 0 }; // Determine sign as 1 for negative, 0 for positive
|
||
|
(mantissa | (sign << 23), exponent) // Include the sign bit in the mantissa
|
||
|
}
|
||
|
|
||
|
pub fn decode_float(mantissa: i32, exponent: i32) -> f32 {
|
||
|
let sign_bit = ((mantissa >> 23) & 1) as u32; // Extract the sign bit
|
||
|
let mantissa_bits = (mantissa & 0x007FFFFF) as u32;
|
||
|
let exponent_bits = (exponent as u32 & 0xFF) << 23;
|
||
|
let bits = (sign_bit << 31) | exponent_bits | mantissa_bits; // Reconstruct all bits including sign
|
||
|
f32::from_bits(bits)
|
||
|
}
|
||
|
|
||
|
#[cfg(test)]
|
||
|
mod tests {
|
||
|
use super::*;
|
||
|
|
||
|
#[rustfmt::skip]
|
||
|
#[test]
|
||
|
fn test_encode_decode() {
|
||
|
let original_floats = [
|
||
|
0.0, 1.0, -1.0, 123.456, -123.456, 1e-10, -1e10, f32::MAX, f32::MIN,
|
||
|
];
|
||
|
for &original in &original_floats {
|
||
|
let (mantissa, exponent) = encode_float(original);
|
||
|
let decoded = decode_float(mantissa, exponent);
|
||
|
assert!(
|
||
|
(decoded - original).abs() < 1e-6,
|
||
|
"Mismatch: original {} vs decoded {}",
|
||
|
original,
|
||
|
decoded
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|