Numbers are at the core of learning any programming language. From basic arithmetic operations to complex computations, numbers are everywhere in programming. Having a strong foundation on numbers and arithmetic would come a long way in mastering any programming language. In this article, ten basic Python programs that involve numbers and arithmetic are explored.

**Disclaimer: **All the examples provided in this post are run using Python 3.12 version. If a different version of Python is used, please make modifications in code as appropriate whenever issues are seen.**Validating user input to be a number**

Python provides two forms of numbers, whole numbers (including negative) are represented as integers, which do not have a fraction associated with it and floating point numbers which has a fraction part. Most of the programs get input from the user to perform further operations. The first step after getting the user input is to validate the input to be in the required format.

Usually input is taken in string format, and later parsed to covert it to a numeric format. To achieve the conversion, Python provides two built-in functions int() and float() to parse an input string and covert it to the respective number format. If any format related errors are encountered during the parsing, a ValueError exception is raised. Using these built-in functions, user input can be validated and parsed to an expected number format.

The first program provides two functions is_integer() and is_float() to verify the given input to be of a specific format. The function relies on the Exception model to return the result to the caller. The code (and for most code in the article) is validated using a bunch of unit tests that evaluate various cases.

def is_integer(string): try: int(string) return True except ValueError: return False def is_float(string): try: float(string) return True except ValueError: return False def run_int_tests(): assert is_integer("1090") assert is_integer("216") assert is_integer("0") assert is_integer("9087680") assert not is_integer("1a0") assert not is_integer("1.0") assert not is_integer("0.00z") assert not is_integer("abc") def run_float_tests(): assert is_float("90.8911") assert is_float("20.001") assert is_float("0.0") assert is_float("9087680") assert not is_float("1a0") assert not is_float("1.aaa0") assert not is_float("ab.cc") assert not is_float("20.iin") run_int_tests() run_float_tests()

**Determining whether a number is even**

The whole numbers that are divisible by 2 are called even numbers, and the numbers which are not even numbers are called as odd numbers. One of the simplest programs to write is to determine whether an input number is even. To achieve this, the number will be taken a modulo of 2 if the result is 0 then the number is even, otherwise odd. The code can be written in a one-liner return num % 2 == 0. However, The example uses the optimized bitwise operation approach, with which the last bit on the integer is extracted if the last bit is 0, then the number is even otherwise odd.

def is_even(num): return num & 1 == 0 def is_odd(num): return num & 1 != 0 def run_tests(): odds = [1, 3, 5, 11, 33, 79, 91, 99, 201] evens = [2, 6, 8, 42, 66, 82, 106, 222, 46] for num in odds: assert is_odd(num) assert not is_even(num) for num in evens: assert is_even(num) assert not is_odd(num) run_tests()

**Finding factors of a given number**

A number x is said to be a factor of number n, when x is less than or equal to n and n mod x = 0. For example, the number 4 has three factors [1, 2, 4]; all of these factors satisfy the condition above. For all numbers, 1 and itself are factors, so any number greater than 1 will have at least two factors.

To find the factors of a given number, division method is used. Starting from 1 to the square root of the number, if the given number is perfectly divisible by the current factor, then two factors will be obtained. The factor, which divides the given number, and the numerator of the division. To only have unique entries, the obtained factors are added to a set. After all the iterations, the factors found so far are returned. The code and output of the execution are as follows,

import math def factors(num): common_factors = set() for i in range(1, int(math.sqrt(num) + 1)): if num % i == 0: factor1 = i factor2 = int(num / i) common_factors.add(factor1) common_factors.add(factor2) return common_factors for curr in [1, 2, 10, 100, 36, 49]: print(f"{curr:3d} - {sorted(factors(curr))}")

After executing the code above, the below output is observed on the console.

1 - [1] 2 - [1, 2] 10 - [1, 2, 5, 10] 100 - [1, 2, 4, 5, 10, 20, 25, 50, 100] 36 - [1, 2, 3, 4, 6, 9, 12, 18, 36] 49 - [1, 7, 49]

**Determining whether a number is prime**

A number is said to be prime, if it only has two factors i.e., 1 and itself. There are some special cases with prime numbers,

- 1 is not a prime number, since it has only one factor
- 2 is the only even prime, all other even numbers are not prime

While we can reuse the factor program to get all the factors, count the number of factors to be 2 and determine prime numbers, it is not optimal. Every number from 1 to the square root of the given number is used in the division. Writing a prime number detector could short-circuit most non-prime cases with the least amount of computation.

The code for detecting prime numbers works as follows,

check for even numbers other than 2, if an even number is found return not-prime

the iteration starts from 3, goes till the square root of the number, in steps of 2 (only odd factors)

with each iteration, if the given number is divisible by the current factor, return not-prime

With the above logic, most of the non-prime numbers are detected on getting the first factor, while prime numbers run the entire loop with no available factors.

import math def is_even(num): return num % 2 == 0 def is_prime(num): # special case handling if num < 2: return False if num != 2 and is_even(num): return False for i in range(3, int(math.sqrt(num) + 1), 2): if num % i == 0: return False return True def run_tests(): primes = [2, 3, 5, 7, 11, 17, 19, 29, 97, 31] non_primes = [1, 0, 6, 9, 25, 49, 80, 81, -3] for num in primes: assert (is_prime(num)) for num in non_primes: assert (not is_prime(num)) run_tests()

**Finding factorial of a given number**

The factorial of a number is computed by multiplying all the numbers from 1 (or -1 in case of negative numbers) to the number. For example, factorial of three would be 3 * 2 * 1 = 6. Similarly, for negative three, it would be -3 * -2 * -1 = -6. The factorial starts with 1 and for all the numbers till the end, the number will multiply the current factorial value in the iteration.

Handling negative numbers is fairly easy, every two multiplications of negative numbers will yield a positive number. So, the number of multiplications decides the sign of the result. If the number of multiplications is odd, then the result will be negative otherwise positive.

def is_odd(num): return num & 1 != 0 def fact(num): is_negative = False if num < 0: num = abs(num) is_negative = True result = 1 for i in range(1, num + 1): result *= i return -result if is_negative and is_odd(num) else result def run_tests_positive_numbers(): assert (fact(0) == 1) assert (fact(1) == 1) assert (fact(2) == 2) assert (fact(3) == 6) assert (fact(4) == 24) assert (fact(5) == 120) assert (fact(6) == 720) def run_tests_negative_numbers(): assert (fact(-1) == -1) assert (fact(-2) == 2) assert (fact(-3) == -6) assert (fact(-4) == 24) assert (fact(-5) == -120) assert (fact(-6) == 720) run_tests_positive_numbers() run_tests_negative_numbers()

**Generate the Fibonacci series**

The Fibonacci starts with the pair of numbers (1, 1), and every following number will be the sum of the previous two numbers in the series. Extending the series from the base pair would look like 1, 1, 2, 3, 5, 8, 13, and so on. To achieve such a sequence, the initial numbers are set to 1. The next number is computed using the sum of the two numbers, after the sum is computed, the current first number becomes the earlier second number and the current second number becomes the result of the sum. The series can be extended to an arbitrary length based on the user input.

def fib(count): curr_num = 1 next_num = 1 for i in range(count): print(curr_num) temp = curr_num + next_num curr_num, next_num = next_num, temp fib(10)

After executing the code above, the below output is observed on the console.

1 1 2 3 5 8 13 21 34 55

**Count digits in a number**

For counting, it would be easier to convert the number to a string and then take the length of the string. However, the approach explored below would use basic arithmetic operations to achieve the same result. Till the number becomes zero, it is repeatedly divided (integer division, where the fractional part will be truncated). For every successful division, the count of digits is incremented by 1. Only the absolute value of the number is considered i.e., sign is dropped while counting the digits.

def get_num_digits(num): num = abs(num) if num == 0: return 1 num_digits = 0 while num > 0: num_digits += 1 num = num // 10 return num_digits def run_tests(): assert get_num_digits(0) == 1 assert get_num_digits(1) == 1 assert get_num_digits(3) == 1 assert get_num_digits(12) == 2 assert get_num_digits(589) == 3 assert get_num_digits(1099) == 4 assert get_num_digits(21344) == 5 assert get_num_digits(978911) == 6 assert get_num_digits(7967499) == 7 run_tests()

**Determining whether a number is Armstrong number**

An Armstrong number is one where the sum of each digit in the number raised to the power of total digits will yield the number. For example, 153 is an Armstrong number, the number of digits is 3 and 1^3 + 5^3 + 3^3 = 153. Since the number of digits needs to be computed, the code above can be reused (imported). Each digit value is obtained by taking the modulo of the current number by 10, and then doing an integer division of the number by 10, till the number is greater than zero. After the current digit is obtained, it is raised to the power of total digits and added to the running sum. After the sum is computed, it is compared with the input number to determine whether it satisfies the properties of being an Armstrong number.

from digits import get_num_digits def is_armstrong_number(num): num_digits = get_num_digits(num) if num_digits == 1: return True tmp_sum = 0 tmp_num = num while num > 0: digit = num % 10 tmp_sum += digit ** num_digits num = num // 10 return tmp_sum == tmp_num def run_tests(): arm_array = [ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [153, 370, 371, 407], [1634, 8208, 9474], [54748, 92727, 93084], [548834], [1741725, 4210818, 9800817, 9926315], [24678050, 24678051, 88593477], [146511208, 472335975, 534494836, 912985153], ] for num_array in arm_array: for num in num_array: assert is_armstrong_number(num) run_tests()

**Reverse a given number**

Similar to counting digits, converting the number to a string would help in reversing the number. However, the approach uses integers and arithmetic to reverse the digits in a given number. The last digit in the number is obtained first by doing a modulo with 10. The current sum is multiplied by 10 and then the digit is added. After the last digit is obtained, a numeric division of the number is performed on the number to get the next digit. The process repeats till there are no more digits. The workflow for reversing the number 123 is as follows,

- get the last digit (which is 3)
- sum = 0 * 10 + 3 = 3, number = 123 at this point
- divide the number by 10 (integer division)
- sum = 3, number = 12
- get the last digit (which is 2)
- sum = 3 * 10 + 2 = 32, number = 12 at this point
- divide the number by 10 (integer division)
- sum = 32, number = 1 at this point
- get the last digit (which is 1)
- sum = 32 * 10 + 1 = 321 and num is 1
- divide the number by 10 (integer division)
- sum = 321, num = 0 (program ends, number is reversed)

def reverse_num(num): cur_num = num rev_num = 0 while cur_num != 0: digit = cur_num % 10 cur_num = cur_num // 10 rev_num = rev_num * 10 + digit return rev_num def run_tests(): assert reverse_num(100) == 1 assert reverse_num(101) == 101 assert reverse_num(1528) == 8251 assert reverse_num(9922122) == 2212299 assert reverse_num(89121) == 12198 assert reverse_num(9) == 9 assert reverse_num(0) == 0 run_tests()

**Determine whether a given number is palindrome**

A palindrome number is one where if the digits are reversed, it will yield the same number. For example, 101 is a palindrome number. Given we have the code to reverse the digits in a number, finding a palindrome number would be as easy as comparing it with the digits reversed.

from rev import reverse_num def is_palindrome(num): return num == reverse_num(num) def run_tests(): pal = [ 101, 11, 1, 2, 5, 1001, 2332, 66866, 9080809, 0, 48984 ] non_pal = [ 100, 189, 211, 878933, 39479, 3204, 123, 34344, 1222 ] for num in pal: assert is_palindrome(num) for num in non_pal: assert not is_palindrome(num) run_tests()

Thanks for reading, hope that some useful information was taken away from this article. Please feel free to leave suggestions and/or comments below.

## Comments

## Post a Comment