How to Calculate and Format Factorials in Python
The factorial of a non-negative integer n, denoted as n!, is the product of all positive integers less than or equal to n. For example, 5! = 1 × 2 × 3 × 4 × 5 = 120. By definition, the factorial of 0 is 1.
This guide explains how to write a Python function that not only calculates the factorial but also formats the output to show the multiplication process (e.g., 3! = 1 * 2 * 3 = 6), while handling invalid inputs gracefully.
Understanding the Logic
To calculate a factorial manually in Python without using the math library, we typically use an iterative approach (a loop).
- Initialize a result variable to 1.
- Iterate from 1 up to
n. - Multiply the current number into the result.
- Track the numbers to create a formatted string string.
Step 1: Handling Edge Cases (Negatives and Zero)
Mathematically, factorials are not defined for negative numbers. Your function should reject negative inputs and explicitly handle the special case of 0!.
def check_input(n):
# ⛔️ Incorrect: Ignoring negative inputs leads to infinite loops or wrong logic
# if n == 0: return 1
# ✅ Correct: Raise an error for negatives, handle 0 explicitly
if n < 0:
raise ValueError("Please enter a non-negative integer.")
elif n == 0:
return "0! = 1"
return "Input is valid"
Always validate input boundaries. Passing a negative number to a standard factorial loop might result in 1 (because the loop range 1 to -5 is empty), which is mathematically incorrect.
Step 2: Implementing the Calculation Loop
To display the full calculation (e.g., 1 * 2 * 3), we need to store each number as a string in a list, then join them together.
n = 5
result = 1
factors = []
# Loop from 1 to n (inclusive)
for i in range(1, n + 1):
result *= i # Multiply to get the math result
factors.append(str(i)) # Store string for display
# Join list with multiplication symbol
factors_str = " * ".join(factors)
print(f"{n}! = {factors_str} = {result}")
Output:
5! = 1 * 2 * 3 * 4 * 5 = 120
Complete Code Implementation
Here is the complete factorial.py script. It includes docstrings, error handling, and the logic to format the output string exactly as requested.
def factorial(n):
"""
Calculate the factorial of a non-negative integer.
Args:
n (int): The non-negative integer.
Returns:
str: Formatted string "{n}! = {factors} = {result}"
Raises:
ValueError: If input is negative.
"""
# 1. Handle Edge Cases
if n < 0:
raise ValueError("Please enter a non-negative integer.")
elif n == 0:
return "0! = 1"
# 2. Perform Calculation
else:
result = 1
factors = []
# Iterate from 1 to n
for i in range(1, n + 1):
result *= i
factors.append(str(i))
# 3. Format Output
factors_str = " * ".join(factors)
return f"{n}! = {factors_str} = {result}"
if __name__ == "__main__":
# Test Cases
try:
print(factorial(2))
print(factorial(8))
# Uncomment to test error handling:
# print(factorial(-5))
except ValueError as e:
print(f"Error: {e}")
Execution Output:
2! = 1 * 2 = 2
8! = 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 = 40320
For pure mathematical calculation in production code (where you don't need the string formatting), use the standard library:
import math; print(math.factorial(5))
Conclusion
Building a custom factorial function helps understand iterative logic and string manipulation.
- Validate Input: Ensure
n >= 0. - Accumulate: Use
result *= iinside a loop. - Format: Use a list and
.join()to construct detailed output strings dynamically.