7
\$\begingroup\$

This program calculates the 7th digit of a GTIN-8 barcode and calculates the validity of an 8 digit GTIN-8 barcode. Could I simplify my code any further?

import math 
def roundup(x): 
 return int(math.ceil(x / 10.0)) * 10 
def doMaths(number): 
 count = 0
 total = 0 
 for n in number: 
 n = int(n) 
 if count %2 == 0: 
 total += n * 3 
 else: 
 total += n 
 count += 1
 if len(number) == 8:
 if total %10 == 0: 
 print("Valid")
 else:
 print("Invalid")
 else:
 print(number + str(roundup(total) - total)) 
while True:
 try:
 number = input("Enter a 7 or 8 digit number for testing: ")
 i = int(number)
 if len(number) == 7 or len(number) == 8:
 doMaths(number)
 break
 else:
 print("Length of number must be 7 or 8")
 continue
 except ValueError:
 print("Only enter numbers.")
 continue
200_success
146k22 gold badges190 silver badges478 bronze badges
asked Oct 5, 2016 at 18:29
\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

The doMaths function has no clear purpose — hence its weird name. It acts as both to calculate the expected last digit of a 7-digit input and to validate the last digit of an 8-digit input. Furthermore, it prints its results instead of returning them, hindering reuse of the function.

What you really want to do is share the code that calculates total. You could write a function like this, using slices:

def gtin8_checksum_digit(number):
 """
 Given a 7- or 8-digit string, calculate the expected GTIN-8 checksum.
 >>> gtin8_checksum_digit('3141592')
 '7'
 >>> gtin8_checksum_digit('31415927')
 '7'
 """
 total = sum(3 * int(d) for d in number[0:7:2]) + \
 sum(int(d) for d in number[1:6:2])
 return str(10 - (total % 10))

No floating-point arithmetic should be necessary.

Note the docstring, and in particular, the doctests that make it clear how the function behaves.

To use that function...

if __name__ == '__main__':
 while True:
 try:
 number = input("Enter a 7 or 8 digit number for testing: ")
 int(number) # Trigger possible ValueError
 if 7 <= len(number) <= 8: break
 print("Length of number must be 7 or 8")
 except ValueError:
 print("Only enter numbers.")
 if len(number) == 8:
 print("Valid" if gtin8_checksum_digit(number) == number[7] else "Invalid")
 else:
 print(gtin8_checksum_digit(number))
answered Oct 5, 2016 at 19:47
\$\endgroup\$
2
  • \$\begingroup\$ @Graipher That concern did cross my mind. How about Rev 3? \$\endgroup\$ Commented Oct 6, 2016 at 13:37
  • \$\begingroup\$ Definitely better. Although I would put the break on its own line for PEP8 compliance. \$\endgroup\$ Commented Oct 6, 2016 at 14:31

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.