1

In Python 2.7, how could I convert floating point decimal (from Decimal module) to binary representation (series of bytes, that I can record to a binary file and read back)? I am interested in smallest possible binary representation. Thanks in advance!

mariaza
  • 33
  • 3
  • what if there is no perfect binary repr? – Joran Beasley Dec 03 '13 at 21:11
  • 2
    That sounds like a lot of work. I recommend using `pickle` instead. – Kevin Dec 03 '13 at 21:11
  • Might be something in the struct module apparently: (possibly related: http://stackoverflow.com/questions/444591/convert-a-string-of-bytes-into-an-int-python) @JoranBeasley Wow they've got memory now that holds bit sequences that files can't? –  Dec 03 '13 at 21:11
  • ... some decimal fractions cannot be expressed accurately as floats ... regardless of medium – Joran Beasley Dec 03 '13 at 21:14
  • 1
    @JoranBeasley Yes, `double` is not as precise for certain ranges as other decimal representations, but I assume it still is stored as a sequence of bytes in memory. (whether contiguous or not) –  Dec 03 '13 at 21:15
  • 1
    `pickle` it and compress it with something. – user2357112 Dec 03 '13 at 21:20
  • 1
    You need to clarify "smallest possible". In real life, the smallest possible representation would require crafting a compression scheme based on the exact values you're storing. If you just want something "reasonably compact", what's wrong with `str(a_decimal)`? Since that produces few distinct characters (digits, `.`, `+`, `-`, `e` ...), feeding that in turn into any compression method would save "a lot" of bytes. – Tim Peters Dec 03 '13 at 21:41

2 Answers2

3

Perhaps something like this? Personally, I'd write the data in ASCII though - writing in binary usually isn't worth it.

#!/usr/local/cpython-2.7/bin/python

import pickle as pickle_mod
import decimal as decimal_mod

decimal = decimal_mod.Decimal(str(1.0 / 9.0))

pickled = pickle_mod.dumps(decimal)
#print repr(pickled)

with open('decimal.bin', 'wb') as file_:
    file_.write(pickled)

with open('decimal.bin', 'rb') as file_:
    data = file_.read()
decimal2 = pickle_mod.loads(data)
print decimal2
dstromberg
  • 6,954
  • 1
  • 26
  • 27
  • and thats alot more bytes than my solution ... but yeah +1 since this does what OP asks (at least as I understand what they want) – Joran Beasley Dec 03 '13 at 21:42
0
my_float = Decimal("1.23")

with open("some_file.bin","w") as f:
      f.write("%s"%my_float.to_eng_string()) #string is a series of bytes

print Decimal(open("some_file.bin").read()) #decoded bytes back to Decimal

this is essentially how the internal representation of Decimal is

The structure will be a tuple of three elements: sign, number and exponent. The sign is 1 or 0, the number is a tuple of decimal digits and the exponent is a signed int or long

Decimal((1, (3, 2, 2, 5), -2)) # for -32.25

Community
  • 1
  • 1
Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
  • Don't you need to read from the file? That point aside though, I don't think that this is what OP is looking for. – mgilson Dec 03 '13 at 21:15
  • 1
    I agree ... but Im not sure the OP knows what they are looking for ... and this technically meets the question defintion ... – Joran Beasley Dec 03 '13 at 21:16
  • clarified slightly ... – Joran Beasley Dec 03 '13 at 21:29
  • 1
    They did say they're using floats from the `decimal` module, so you should change this to not use binary floats. But apart from that, I agree this is the best possible response (given that the poster really doesn't know what they want ;-) ). – Tim Peters Dec 03 '13 at 21:29
  • 1
    @TimPeters -- Yeah, I think I agree with that statement. Perhaps rather than guessing what OP wants, we should all vote to close as "unclear" since that seems to be the consensus among the comments and answers given so far ... – mgilson Dec 03 '13 at 21:32
  • @JoranBeasley -- and FWIW, I'm not your downvoter ;-) – mgilson Dec 03 '13 at 21:33
  • I figured :P ... I think its OP (and I seconded your vote) :P – Joran Beasley Dec 03 '13 at 21:34