homer512 icon

Int2BCD

homer512 | PRO | 08/19/15 07:26:14 PM UTC | 0 ⭐ | 934 👁️ | Never ⏰ | []
Python |

1.8 KB

|

None

|

0 👍

/

0 👎

#!/usr/bin/python3
 
 
def make_nibbles(dec, high):
    """Translates half of the dec digits into BCD nibble values
 
    Arguments:
    dec -- a bytes object of decimal digits. Length has to be a multiple of 2
    high -- defines if the high or low nibble per byte should be calculated
 
    Return value:
    A bytes object representing the nibbles. The nibble that is not calculated
    (per byte) is set to 0
    """
    assert(not (len(dec) & 1))
    # build a translation table from decimal digits to BCD nibble values
    translate_from = b'0123456789'
    bitshift = 4 if high else 0
    translate_to = bytes(num << bitshift for num in range(10))
    # TODO: This table should only be calculated once and reused afterwards
    table = bytes.maketrans(translate_from, translate_to)
    byteshift = 0 if high else 1
    bytes_ = dec[byteshift::2]
    return bytes_.translate(table)
 
 
def int2bcd(value):
    """Encodes an integer into a bytes object of packed BCD values"""
    dec = bytes(str(value), 'ascii')
    padded_len = (len(dec) + 1) >> 1 << 1
    padded_dec = dec.rjust(padded_len, b'0')
    nibbles_low = make_nibbles(padded_dec, high=False)
    nibbles_high = make_nibbles(padded_dec, high=True)
    return bytes(high | low for high, low
                 in zip(nibbles_high, nibbles_low))
 
 
def bcd2int(bcd):
    lowmask = (1 << 4) - 1
    bytevals = [(byte_ & lowmask) + 10 * (byte_ >> 4) for byte_ in bcd]
    return sum(byteval * 100**pow_ for pow_, byteval
               in enumerate(reversed(bytevals)))
    
 
def main():
    value = int('42132801305034541=4101210013390'.replace("=", 'D'), 16)
    bcd = int2bcd(value)
    intval = bcd2int(bcd)
    print("%d (%d) -> %s (%d) = %d" % (value, len(str(value)), bcd, len(bcd), intval))
 
 
if __name__ == '__main__':
    main()

Comments