Solidity – Convert IEEE754 Quad Precision Float from bytes16 to Human-Readable Decimal String

solidityweb3js

I have a solidity smart contract project that uses lots of floating point operations like Pow, ln, exp, etc, but I need more precision than normal 64 bit doubles. I am planning to use the ABDKMathQuad library which implements IEEE754 quadruple precision floating point numbers, which are stored as bytes16. I want to use a high level language to grab the bytes16 float value from the Ethereum block chain and display it as a decimal. Is there an easy way to do this? Here's my simple test code:

contract MyContract{

    using ABDKMathQuad for uint256;
    using ABDKMathQuad for int256;
    using ABDKMathQuad for bytes16;

    function get_float() public view returns(bytes16){
        uint256 int_numerator = 135335283236613;
        uint256 int_denominator = 1000000000000000;
        bytes16 float_numerator = int_numerator.fromUInt();
        bytes16 float_denominator = int_denominator.fromUInt();
        bytes16 float_result = float_numerator.div(float_denominator);
        return float_result; //returns 0.135335283236613 as a bytes16 data type
    }
}

get_float() returns:

{
    "0": "bytes16: 0x3ffc152aaa3bf81d6b9a230830957429"
}

I raised an issue with the creator of the ABDK library on github:
https://github.com/abdk-consulting/abdk-libraries-solidity/issues/24

He provided me a nice toolkit for converting it manually:
https://toolkit.abdk.consulting/math#convert-number

When I plug 0x3ffc152aaa3bf81d6b9a230830957429 into the toolkit, I get 0.135335283236612999999999999999999988

I want to use a high level language, preferably python, to do many such conversions of bytes16 to decimal so that I can debug easily. Is there an easy way to do this?

Thank you

Best Answer

I found a python library called anyfloat, which does exactly what I need.

I wrote a basic script using brownie and anyfloat:

from anyfloat import anyfloat
from decimal import Decimal

import brownie
from brownie import *
p = project.load('.', name="brownieTutorial")
p.load_config()
from brownie.project.brownieTutorial import *
network.connect('development')

def get_float(float_128):
    size = (15, 112)
    a = anyfloat.from_ieee(int(str(float_128), 16), size)
    f = a.to_fraction()
    dec = round(Decimal(f.numerator)/Decimal(f.denominator), 36)
    return dec

myContract = MyContract.deploy({"from": accounts[0]});
print('float value: ', get_float(myContract.get_float()))
Related Topic