Subscribe to the RSS feed by copy/paste the link below
RSS

Floating Point to Fraction Convertion Using Python

Posted by Admin on 14. August, 2018
MyBlog ยป

Normally in order to multiply x by 1.234 the floating point library needs to be #included however, this increases the code size substantially.; which can be a problem with memory limited microcontrollers.

A solution is to use integers that can be manipulated without floating points and that fit into 8 bits.  Since accuracy is an issue I had to decide what are the permissable errors, so the script gives me the error too.  If the errors are within acceptable limits this method works fine and keeps the code small.  More modern controllers, like the Atmel128, have much larger memories built in so including the floating point libraries is not so much of an issue, for the smaller chips, such as the Attiny45 though it's still useful.

#!/bin/env python
"""
To derive a fractional equivalent of a decimal fraction
A Python equvalent for dec2frac.c
TODO Add listing of solutions perhaps
  Add code to find smallest possible fraction.  Although we seem to get that anyway.
  Should first try to get an exact solution then use ERROR value
  Or make error very small then increase if solutions are not computed
$Id: dec2frac.py,v 1.1 2010/07/20 12:36:45 mikee Exp $
"""

import math
import sys

# Define stuff here
frac = 0
ERROR = 0
MAX_SIZE = 255

#From http://www.daniweb.com/forums/thread70650.html
'''check if integer n is a prime'''
def isprime(n):
# range starts with 2 and only needs to go up the squareroot of n
  for x in range(2, int(n**0.5)+1):
    if n % x == 0:
      return False
  return True

# C struct equivalent to return results
class Fraction():
  numer = None
  denom = None

def DoFraction(frac, f):
  num = 0
  denom = 1
  while True:
    num += 1
    denom = int(num / frac)
    if num >= MAX_SIZE or denom >= MAX_SIZE:
      print ">= MAX_SIZE. Solution is probably not useful."
      break
    if float((abs((float(num)/float(denom)) - float(frac))) < ERROR):
      print "Solution is useful."
      break
  f.numer = int(num)
  f.denom = int(denom)
  return f
 
# START HERE
if len(sys.argv) != 2:
  print 'Usage:', sys.argv[0], 'Some fraction'
  print ''
  sys.exit(1)

try:
  frac = float(sys.argv[1])
except :
  print "Input a fraction please"
  print ''
  sys.exit(1)

print frac
# Bigger than 1?
if frac > 1:
  print "Input only the decimal fraction part."
  print ''
  sys.exit(1)

ERROR = frac / 10000000
fraction = Fraction()
# Loop until we find a least error solution
while True:
  DoFraction(frac, fraction)
  if fraction.denom < MAX_SIZE and fraction.numer < MAX_SIZE:
    break
  ERROR *= 10 # increase the allowable error  
fract = float(fraction.numer) / float(fraction.denom)
print fraction.numer,'/',fraction.denom
print 'Calculated fraction =', fract  # Prints spaces, I DON'T WANT SPACES!!!
print 'Absoluter error =',  ((float(fraction.numer)/float(fraction.denom)) - frac)
print 'Percentage error =', (((float(fraction.numer)/float(fraction.denom)) - frac) * 100) / frac, "%"


Just use the resulting fraction in your embedded code to save a whole lot of space and get faster excution. Mostly the residual error can be ignored. Obviously don't use this for critical applications because this isn't rocket science approved. But then again...

 

Last changed: 14. August, 2018 at 14:05

Back to Overview