ajmartin
ajmartin

Reputation: 2409

Retrieving fixed point value from binary string

I am implementing an Arithmetic Encoder & Decoder. A sub-module of it deals with converting fixed point value to binary and vice verse.

The strings which are to be encoded are pretty long therefore I have to consider a lot of precision= 250. Once I have a Decimal value; it is being converted to a binary string (def decimal_to_binary_str). The issue is to retrieve the Decimal value from the binary def binary_str_to_decimal. Can someone point the issue?

import decimal

def decimal_to_binary_str(f, l):
    res = ""
    var = f - int(f)
    while var != 0 and len(res) < l:
        var = var*2
        res += '{0:.250f}'.format(var)[0]
        var = var - int(var)
    return res

def binary_str_to_decimal(bit_str):
    a = decimal.Decimal(0)
    b = decimal.Decimal(1)
    res = decimal.Decimal(0.5)

    for j in bit_str:
        if j == '0':
            b -= (b-a)/2
            res = res - (b-a)/2
        elif j == '1':
            a += (b-a)/2
            res = res + (b-a)/2
    return res

if __name__ == "__main__":
    decimal.setcontext(decimal.Context(prec=250))
    f = decimal.Decimal('0.2157862006526829178278743649908677246339070461540076509576931506281654871337287537411826845238756634211771470806684727059082493570941004017476336218118077112203256327565095923853074403357680122784788435203804147809638828466085270584355766316314164101')
    print f
    b = decimal_to_binary_str(f, 669)
    print binary_str_to_decimal(b)


  '''
    I have marked with pipe symbol(|) the difference in what is retrieved and what was the original.
    Output: 
0.215786200652682917827874364990867724633907046154007650957693150628165487133728753741182684523875663421177147080668472705908249357094100401747633621811807711220325632756509592385307440335768012278478843|5203804147809638828466085270584355766316314164101  
0.215786200652682917827874364990867724633907046154007650957693150628165487133728753741182684523875663421177147080668472705908249357094100401747633621811807711220325632756509592385307440335768012278478843|3376547904539139004978887353289003223234434034223
    '''

Upvotes: 1

Views: 124

Answers (1)

Jose Varez
Jose Varez

Reputation: 2077

The issue is with the decimal_to_binary_str function. When you stop that function after 699 bits you are truncating information. That lost of information is what you see when you convert it back to decimal. You can see this clearly if you play with different output lengths:

f = decimal.Decimal('0.31')
out = decimal_to_binary_str(f, 64)
print binary_str_to_decimal(out)
Out: 0.30999999999999999997506335003283339801782858557999134063720703125
out = decimal_to_binary_str(f, 128)
print binary_str_to_decimal(out)
Out: 0.310000000000000000000000000000000000000411423022787800627789057788027785987236532944870230632528063097197446040809154510498046875
out = decimal_to_binary_str(f, 256)
print binary_str_to_decimal(out)
Out: 0.3100000000000000000000000000000000000000000000000000000000000000000000000000029362973087321111726313596333521358541794401239083356709080591798573212130752251997103125511805779970305860799416908856229783336419228618758420212841997454233933240175247192

It never really converges to the original number. The issue of finding a binary representation of a decimal number is a complex one. Look into the IEEE 754 standard and similars.

Upvotes: 1

Related Questions