I tagged this question as javascript because even though I currently wrote this in Python, if it would be easier to implement in Javascript, I could easily implement it in Javascript.
My assignment is to make a significant figure calculation checker for the chemistry department . What that means is that the student enters their data into the fields, the web app will perform predefined operations on their fields and keep track of significant figures and see if their answer has the proper number of significant figures.
When I broke the problem down into what I figure is a good work flow, I realized that I would need a way for either Python (the backend since this is a web app made in Django) or Javascript (cause you could always validate it on the front end no problem) to determine the number of significant digits. I did a little research and came across this question which tells me that I needed to work with python strings instead of floats. My current python code feels ALMOST complete, but there is still one major challenge I face
import re
def find_sigfigs(x):
# change the 'E' to lower case if the student typed it in as uppercase
x = x.lower()
if ('e' in x):
myStr = x.split('e')
# this function assumes that the number on the left of the 'e' is
# the number of sigfigs. That would be true for user input but not
# true when python converts a float to scientific notation
return len( (re.search('[0-9]+', myStr[0])).group() )
else:
# put it in e format and return the result of that
### problem: python makes me hard code the number of sigfigs as '2'
### without the 2 there it always defaults to 6
return find_sigfigs('%.*e' %(2,float(x)))
>>> find_sigfigs('1.3e-4')
>>> 2
>>> find_sigfigs('1234')
>>> 3
>>> find_sigfigs('123456')
>>> 3
>>> find_sigfigs('1.2345e3')
>>> 5
then without the 2
return find_sigfigs('%.e' %(float(x)))
#Because it changes it to 1.234000e3
>>> find_sigfigs('1234')
>>> 7
#Because it changes it to 1.234560e5
>>> find_sigfigs('123456')
>>> 7
So simply put, my problem is that I need a simple way to count the sigfigs when it is not explicitly declared by the student (aka when it is in scientific notation). Is there some easy way that I could drop every zero before the 'e' until it gets to the first non zero digit. I guess, I need to start from the back of the split string and remove zeros until it gets to a nonzero digit?
EDIT: So after a little more fiddling, I hope this is an appropriate solution to the problem. I tested it several times, but not too rigorously (aka it probably works but who knows! I'm not too good at sigfigs...)
def find_sigfigs(x):
'''Returns the number of significant digits in a number. This takes into account
strings formatted in 1.23e+3 format and even strings such as 123.450'''
# change all the 'E' to 'e'
x = x.lower()
if ('e' in x):
# return the length of the numbers before the 'e'
myStr = x.split('e')
return len( myStr[0] ) - 1 # to compenstate for the decimal point
else:
# put it in e format and return the result of that
### NOTE: because of the 8 below, it may do crazy things when it parses 9 sigfigs
n = ('%.*e' %(8, float(x))).split('e')
# remove and count the number of removed user added zeroes. (these are sig figs)
if '.' in x:
s = x.replace('.', '')
#number of zeroes to add back in
l = len(s) - len(s.rstrip('0'))
#strip off the python added zeroes and add back in the ones the user added
n[0] = n[0].rstrip('0') + ''.join(['0' for num in xrange(l)])
else:
#the user had no trailing zeroes so just strip them all
n[0] = n[0].rstrip('0')
#pass it back to the beginning to be parsed
return find_sigfigs('e'.join(n))