debugpythonMinor
Counting significant figures in a number
Viewed 0 times
figuresnumbercountingsignificant
Problem
I decided to make something to count the significant figures in a number to see how easily it could be done, but I think there may have been a better or simpler way. Any advice even just for conventional purposes is appreciated!
```
def count_sig_figs(answer):
'''This fucntion will count the sigfigs used in the answer of a user'''
sig_fig_count = 0
num_list = list(answer)
for index in range(len(num_list)):
try:
fig = int(num_list[index])
if fig != 0:
sig_fig_count +=1
elif check_zero_sig(index, num_list, sig_fig_count):
sig_fig_count += 1
except:
continue
return sig_fig_count
def check_zero_sig(index, num_list, sig_fig_count):
'''Checks for significance in a zero from a list'''
try:
decimal = num_list.index('.')
if index > decimal and sig_fig_count > 0:
return True
except:
if index == 0:
return False
elif index == len(num_list):
return False
new_index = index+1
if num_list[new_index] == '.' and sig_fig_count > 0:
return True
elif num_list[new_index] == '.' and sig_fig_count == 0:
return False
elif num_list[new_index] != '.' and sig_fig_count > 0:
fig = int(num_list[new_index])
if fig != 0:
return True
else:
return check_zero_sig(new_index, num_list, sig_fig_count)
elif num_list[new_index] != '.' and sig_fig_count == 0:
fig = int(num_list[new_index])
if fig != 0:
return True
else:
return check_zero_sig(new_index, num_list, sig_fig_count)
else:
return False
def test():
print(count_sig_figs('1')) # 1 sig fig
print(count_sig_figs('10')) # 1 sig fig
print(count_sig_figs('100')) # 1 sig fig
print(count_sig_figs('1004')) # 4 sig figs
print(
```
def count_sig_figs(answer):
'''This fucntion will count the sigfigs used in the answer of a user'''
sig_fig_count = 0
num_list = list(answer)
for index in range(len(num_list)):
try:
fig = int(num_list[index])
if fig != 0:
sig_fig_count +=1
elif check_zero_sig(index, num_list, sig_fig_count):
sig_fig_count += 1
except:
continue
return sig_fig_count
def check_zero_sig(index, num_list, sig_fig_count):
'''Checks for significance in a zero from a list'''
try:
decimal = num_list.index('.')
if index > decimal and sig_fig_count > 0:
return True
except:
if index == 0:
return False
elif index == len(num_list):
return False
new_index = index+1
if num_list[new_index] == '.' and sig_fig_count > 0:
return True
elif num_list[new_index] == '.' and sig_fig_count == 0:
return False
elif num_list[new_index] != '.' and sig_fig_count > 0:
fig = int(num_list[new_index])
if fig != 0:
return True
else:
return check_zero_sig(new_index, num_list, sig_fig_count)
elif num_list[new_index] != '.' and sig_fig_count == 0:
fig = int(num_list[new_index])
if fig != 0:
return True
else:
return check_zero_sig(new_index, num_list, sig_fig_count)
else:
return False
def test():
print(count_sig_figs('1')) # 1 sig fig
print(count_sig_figs('10')) # 1 sig fig
print(count_sig_figs('100')) # 1 sig fig
print(count_sig_figs('1004')) # 4 sig figs
print(
Solution
num_list is better named digits; don't describe the type, describe the value.test's output is unhelpful; the result should be much more obvious, especially when it fails. Keeping along the given lines, I might do something likedef test():
def should_be(string, count):
assert count_sig_figs(string) == count
print("{!r} has {} sf.".format(string, count))
should_be('1', 1)
should_be('10', 1)
should_be('100', 1)
should_be('1004', 4)
should_be('10004', 5)
should_be('105', 3)
should_be('01', 1)
should_be('1.2035', 5)
should_be('001.09508', 6)
should_be('0.00110', 3)Of course, a proper test suite is probably better.
This isn't idiomatic:
for index in range(len(digits)):
try:
fig = int(digits[index])
if fig != 0:
sig_fig_count +=1
elif check_zero_sig(index, digits, sig_fig_count):
sig_fig_count += 1
except:
continue
return sig_fig_countBare
try...excepts are bad. Evenexcept (ValueError, IndexError):is bad. Primarily this is because you're spreading out the checks where they don't belong and it should instead be
try:
fig = int(digits[index])
except ValueError:
continue
if fig != 0:
sig_fig_count +=1
else:
try:
zero_sig = check_zero_sig(index, digits, sig_fig_count)
except IndexError:
continue
if zero_sig:
sig_fig_count += 1But then because... why is
check_zero_sig throwing an IndexError? Surely that's a bug.Before we get there, quickly change this to
for index, digit in enumerate(digits):
if digit == ".":
continue
if digit != '0':
sig_fig_count += 1
else:
sig_fig_count += check_zero_sig(index, digits, sig_fig_count)That's pretty much what we want expressed more simply.
check_zero_sig's except also needs updating:try:
decimal = digits.index('.')
except ValueError:
...
else:
return index > decimal and sig_fig_count > 0I don't get why you don't just mutate
index instead of using new_index.This can be simplified:
if digits[index] == '.' and sig_fig_count > 0:
return True
elif digits[index] == '.' and sig_fig_count == 0:
return Falseto
if digits[index] == '.':
return bool(sig_fig_count)The
elif digits[index] != '.' and sig_fig_count > 0:and
elif digits[index] != '.' and sig_fig_count == 0:branches are the same.
This then simplifies to
if digits[index] == '.':
return bool(sig_fig_count)
elif digits[index] != '.':
digit = int(digits[index])
return bool(digit) or check_zero_sig(index, digits, sig_fig_count)
else:
return Falsewhich is just
if digits[index] == '.':
return bool(sig_fig_count)
else:
digit = int(digits[index])
return bool(digit) or check_zero_sig(index, digits, sig_fig_count)Then we see
elif index == len(digits):
return Falsecannot fire until after
index += 1. This lets us fix our IndexError.Back to
count_sig_figs. The documentation is not written idiomatically. Documentation should be to the point, direct and not talk in third person.def count_sig_figs(digits):
'''Return the number of significant figures of the input digit string'''
sig_fig_count = 0
for index, digit in enumerate(digits):
if digit == ".":
continue
if digit != '0':
sig_fig_count += 1
else:
sig_fig_count += check_zero_sig(index, digits, sig_fig_count)
return sig_fig_countBack to
check_zero_sig, which is nowdef check_zero_sig(index, digits, sig_fig_count):
'''Checks for significance in a zero from a list'''
try:
decimal = digits.index('.')
except ValueError:
if index == 0:
return False
index += 1
if index == len(digits):
return False
if digits[index] == '.':
return bool(sig_fig_count)
else:
digit = int(digits[index])
return bool(digit) or check_zero_sig(index, digits, sig_fig_count)
else:
return index > decimal and sig_fig_count > 0The
if digits[index] == '.' check can't fire; we're in the except. Thendigit = int(digits[index])
return bool(digit) or check_zero_sig(index, digits, sig_fig_count)can be
return digit != '0' or check_zero_sig(index, digits, sig_fig_count)and the recursion, which would end up re-calling
.index, can just beif index == 0:
return False
return any(digit != '0' for digit in digits[index+1:])index == 0 is a very strange special case; you deal with 01 but not 001 or 00001. I suggest removing the special-case and using sig_fig_count.Now we have
```
def check_zero_sig(index, digits, sig_fig_count):
'''
Returns if a zero digit at a given position is significant,
given a count of significant d
Code Snippets
def test():
def should_be(string, count):
assert count_sig_figs(string) == count
print("{!r} has {} sf.".format(string, count))
should_be('1', 1)
should_be('10', 1)
should_be('100', 1)
should_be('1004', 4)
should_be('10004', 5)
should_be('105', 3)
should_be('01', 1)
should_be('1.2035', 5)
should_be('001.09508', 6)
should_be('0.00110', 3)for index in range(len(digits)):
try:
fig = int(digits[index])
if fig != 0:
sig_fig_count +=1
elif check_zero_sig(index, digits, sig_fig_count):
sig_fig_count += 1
except:
continue
return sig_fig_countexcept (ValueError, IndexError):try:
fig = int(digits[index])
except ValueError:
continue
if fig != 0:
sig_fig_count +=1
else:
try:
zero_sig = check_zero_sig(index, digits, sig_fig_count)
except IndexError:
continue
if zero_sig:
sig_fig_count += 1for index, digit in enumerate(digits):
if digit == ".":
continue
if digit != '0':
sig_fig_count += 1
else:
sig_fig_count += check_zero_sig(index, digits, sig_fig_count)Context
StackExchange Code Review Q#122284, answer score: 2
Revisions (0)
No revisions yet.