Converting decimal to binary with desired significant digits and vice -versa
# Function returns decimal representation
def bin_float(binStr, places = 10):
if binStr.find('.') >= 0:
whole, dec = binStr.split(".")
else:
whole, dec = str(int(binStr)), '0'
x = 0
N = len(whole)-1
for k in range(N+1):
x += int(whole[N-k])*2**k
N = len(dec)
for k in range(N):
dx = int(dec[k])/2**(k+1)
x += dx
return(x)
# Function returns binary representation
def float_bin(x, places = 5):
# Convert an integer number to it's
# respective binary representation
if int(x) == x:
return('{:b}'.format(int(x)))
# Separate x to integer and decimal parts
# and store in two separate variables
whole = int(x)
dec = abs(x - whole)
# Convert the whole number part to it's
# respective binary representation
binStr = '{:b}'.format(whole)+'.'
# Check if |x| > 0 for needed significant digits
Sw = whole != 0
# Iterate for significant/decimal digits
Dig = 0
while (Dig < places):
# Multiply the decimal value by 2
# and separate the whole number part
# and decimal part
dec *= 2
whole = int(dec)
dec = abs(dec - whole)
# Keep adding the integer parts
# receive to the result variable
binStr += str(whole)
# Stating significant digit from non zero value
if Sw:
Dig += 1
else:
Sw = whole != 0
# if last digit is 1, need roundoff truncation
if binStr[-1] == '1':
k = len(binStr)-1
while (k > 0) and (binStr[k] in ['.', '1']):
if binStr[k] == '1':
binStr = binStr[:k]+'0'+binStr[k+1:]
k -= 1
if len(binStr)-1-k > places:
binStr = binStr[:k]+'1'+binStr[k+1:-1]
else:
binStr = binStr[:k]+'1'+binStr[k+1:]
return(binStr[:-1])
Test the code:
def do_for(x, p):
bx = float_bin(x, places = p)
Dx = bin_float(bx)
rel = 100*abs(1-Dx/x)
if rel >= 1:
print('\n value = {:.6e} binary = {} ({} sig. digits)'.format(x, bx, p), \
'\n saved = {:.6e} Error = {:.2f}\%'.format(Dx, rel))
else:
print('\n value = {:.6e} binary = {} ({} sig. digits)'.format(x, bx, p), \
'\n saved = {:.6e} Error = {:.1e}\%'.format(Dx, rel))
do_for(0.234, 8)
do_for(0.234, 3)
do_for(0.234, 2)
do_for(15/16, 4)
do_for(31/32, 4)
do_for(1.00052123, 12)
do_for(0.00052123, 8)
results:
value = 2.340000e-01 binary = 0.0011110000 (8 sig. digits)
saved = 2.343750e-01 Error = 1.6e-01\%
value = 2.340000e-01 binary = 0.00111 (3 sig. digits)
saved = 2.187500e-01 Error = 6.52\%
value = 2.340000e-01 binary = 0.010 (2 sig. digits)
saved = 2.500000e-01 Error = 6.84\%
value = 9.375000e-01 binary = 0.1111 (4 sig. digits)
saved = 9.375000e-01 Error = 0.0e+00\%
value = 9.687500e-01 binary = 1.000 (4 sig. digits)
saved = 1.000000e+00 Error = 3.23\%
value = 1.000521e+00 binary = 1.00000000001 (12 sig. digits)
saved = 1.000488e+00 Error = 3.3e-03\%
value = 5.212300e-04 binary = 0.000000000010001001 (8 sig. digits)
saved = 5.226135e-04 Error = 2.7e-01\%