I am trying to convert from a Q64.96 to a BigFloat. The Q64.96 number is initially represented as a U256 type from the ethers-rs crate.
I first convert the value to big endian bytes. Then I am trying to convert to BigFloat from the num-bigfloat crate.
To do this, I am using the BigFloat::from_bytes associated function but I am not sure how to derive the exponent from bytes when the number represented as a Q64.96. Can someone help me figure out how to convert this value to BigFloat?
I don't think from_bytes
is what you want here. Given that what's stored in the U256
is essentially a 160-bit unsigned integer, I'd construct the BigFloat
directly from the constituent u64
s like so:
fn convert(q64_96: U256) -> BigFloat {
let least_sig = q64_96.0[0];
let second_sig = q64_96.0[1];
let third_sig = q64_96.0[2];
let most_sig = q64_96.0[3];
let bf2 = BigFloat::from(2);
let bf64 = BigFloat::from(64);
let bf128 = BigFloat::from(128);
let bf192 = BigFloat::from(192);
let bf96 = BigFloat::from(96);
(
(BigFloat::from(most_sig) * bf2.pow(&bf192)) +
(BigFloat::from(third_sig) * bf2.pow(&bf128)) +
(BigFloat::from(second_sig) * bf2.pow(&bf64)) +
BigFloat::from(least_sig)
) / bf2.pow(&bf96)
}
However, it may not be perfectly accurate due to how floats work.
I'm curious what your use case for this conversion is. Fixed-point arithmetic is generally more predictable, and the Q64.96 has a ton of precision.