mirror of
https://github.com/FliegendeWurst/ieee754-interpreter.git
synced 2024-11-25 15:24:58 +00:00
Single-precision interpreter
This commit is contained in:
parent
c9c9d525be
commit
e32878d723
77
src/main.rs
77
src/main.rs
@ -1,5 +1,78 @@
|
|||||||
|
use std::error::Error;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
fn main() {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let args = env::args().collect::<Vec<_>>();
|
let args = env::args().skip(1).collect::<Vec<_>>();
|
||||||
|
for arg in args {
|
||||||
|
let binary_value = parse(&arg.replace(' ', ""))?;
|
||||||
|
println!("binary: {:032b}", binary_value);
|
||||||
|
let transmuted = f32::from_bits(binary_value); // clippy was smart enough to notice the transmute to a f32
|
||||||
|
println!("transmuted: {:?}", transmuted);
|
||||||
|
println!("interpreted: {:?}", interpret_single(binary_value));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(binary_number: &str) -> Result<u32, Box<dyn Error>> {
|
||||||
|
if binary_number.len() != 32 {
|
||||||
|
return Err("argument not 32 bits".into());
|
||||||
|
}
|
||||||
|
let mut value: u32 = 0;
|
||||||
|
for (idx, digit) in binary_number.chars().enumerate() {
|
||||||
|
match digit {
|
||||||
|
'0' => {},
|
||||||
|
'1' => value += 1 << (31-idx),
|
||||||
|
x => return Err(format!("argument contains more than 0s and 1s: {:?}", x).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_test() {
|
||||||
|
assert_eq!(parse("10110000111111110101010110101010").unwrap(), 0b10110000111111110101010110101010);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn interpret_single(float: u32) -> f32 {
|
||||||
|
let sign = float.rotate_left(1) & 1;
|
||||||
|
let sign = if sign == 1 { -1.0 } else { 0.0 };
|
||||||
|
let characteristic = float.rotate_left(9) & 0b1111_1111;
|
||||||
|
let mantissa = float & 0b1111_1111_1111_1111_1111_111;
|
||||||
|
|
||||||
|
if characteristic == 0 {
|
||||||
|
if mantissa != 0 {
|
||||||
|
eprintln!("can't process denormalized floats (yet)");
|
||||||
|
return 0.0;
|
||||||
|
} else {
|
||||||
|
return sign * 0.0;
|
||||||
|
}
|
||||||
|
} else if characteristic == 255 {
|
||||||
|
if mantissa != 0 {
|
||||||
|
return f32::NAN;
|
||||||
|
} else {
|
||||||
|
return sign * f32::INFINITY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut power = 2.0f32.powi(characteristic as i32 - 127);
|
||||||
|
let mut value = sign * power;
|
||||||
|
for idx in 0..23 {
|
||||||
|
let digit = (mantissa >> (22 - idx)) & 1;
|
||||||
|
power /= 2.0;
|
||||||
|
if digit == 1 {
|
||||||
|
value += sign * power;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn interpret_single_test() {
|
||||||
|
let tests = [
|
||||||
|
(0b1100_0000_1110_1000_0000_0000_0000_0000, -7.25),
|
||||||
|
(0b1011_1111_0101_0000_0000_0000_0000_0000, -0.8125)
|
||||||
|
];
|
||||||
|
for test in &tests {
|
||||||
|
assert_eq!(interpret_single(test.0), test.1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user