Reputation: 2409
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
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