In Python, numbers are objects just like strings, lists, and dictionaries. This means they have built-in methods and attributes. Additionally, numbers are immutable, meaning their values cannot be changed once created. Instead, new objects are created when operations are performed.

x = 10
print(id(x))  # Memory address of x

x = x + 5
print(id(x))  # Different memory address, because x now refers to a new object

Since numbers are immutable, modifying them does not affect the original value but instead creates a new object.

x = 10
print(id(x)) # Memory address of x

print(id(10)) # The same memory address because Python doesn't need to create the same object twice

y = 10
print(id(y)) # The same memory address

Numeric Types in Python

Python provides three primary numeric types:

  1. Integers (int): Whole numbers (e.g., 1, 42, -1000).
  2. Floating-Point Numbers (float): Numbers with decimals (e.g., 3.14, 2.71, -0.001).
  3. Complex Numbers (complex): Numbers with a real and imaginary part (e.g., 3 + 4j).

Checking the Type of a Number

You can check the type of a number using type():

print(type(42))     # Output: <class 'int'>
print(type(3.14))   # Output: <class 'float'>
print(type(2 + 3j)) # Output: <class 'complex'>
print(type(42) is int)     # True
print(type(3.14) is float)   # True
print(type(2 + 3j) is complex) # True

Integer and Floating-Point Arithmetic

Python provides various operators for performing numerical calculations.

Basic Arithmetic Operations

a = 10
b = 3

print(a + b)   # Addition -> Output: 13
print(a - b)   # Subtraction -> Output: 7
print(a * b)   # Multiplication -> Output: 30
print(a / b)   # Floating-point division -> Output: 3.3333333333333335
print(a // b)  # Floor division -> Output: 3
print(a % b)   # Modulus (remainder) -> Output: 1
print(a ** b)  # Exponentiation -> Output: 1000

Floating-Point Division (/)

The / operator always returns a float, even if the result is a whole number.

print(10 / 2)   # Output: 5.0 (float, not int)
print(7 / 2)    # Output: 3.5

Floor Division (//)

The // operator performs division but rounds down to the nearest whole number. It always returns an integer if both operands are integers and a float if at least one operand is a float.

print(10 // 3)   # Output: 3
print(-10 // 3)  # Output: -4 (rounded down, not towards zero)
print(10.5 // 3) # Output: 3.0

Exponentiation (**)

The ** operator is used to calculate powers.

print(2 ** 3)    # Output: 8 (2^3)
print(5 ** 0.5)  # Output: 2.23606797749979 (square root of 5)

Converting Between Number Types

Python allows easy conversion between number types using int(), float(), and complex().

x = 10         # Integer
y = 3.14       # Float
z = "42"       # String

print(float(x))  # Convert int to float -> Output: 10.0
print(int(y))    # Convert float to int -> Output: 3 (truncates, does not round)
print(int(z))    # Convert string to int -> Output: 42
print(complex(x)) # Convert int to complex -> Output: (10+0j)

Built-in Math Functions

Python provides several built-in functions for working with numbers.

print(abs(-7))    # Absolute value -> Output: 7
print(round(3.14159, 2))  # Rounding -> Output: 3.14
print(pow(2, 3))  # Equivalent to 2 ** 3 -> Output: 8

For advanced math operations, Python’s math module provides additional functionality.

import math

print(math.sqrt(25))   # Square root -> Output: 5.0
print(math.factorial(5)) # Factorial -> Output: 120
print(math.log(100, 10)) # Logarithm base 10 -> Output: 2.0

Working with Large Numbers

Python supports arbitrarily large integers. Unlike many other languages, there is no fixed limit on integer size (except for available memory).

big_number = 10 ** 100  # 10 raised to the power of 100
print(big_number)       # Output: A very large number
print(type(big_number)) # Output: <class 'int'>

For handling large floating-point numbers, Python supports the decimal module, which provides arbitrary-precision arithmetic.

from decimal import Decimal

x = Decimal("0.1") + Decimal("0.2")
print(x)  # Output: 0.3 (precise calculation)

Boolean Operations with Numbers

Since True and False are subclasses of int, they can participate in numerical operations.

print(True + True)  # Output: 2 (1 + 1)
print(False * 10)   # Output: 0 (0 * 10)

However, using boolean values in numeric operations is not a recommended practice unless specifically required.

Common Pitfalls and Best Practices

  1. Floating-Point Precision Issues

    • Floating-point arithmetic is not always exact due to binary representation.
    print(0.1 + 0.2)  # Output: 0.30000000000000004 (unexpected result)
    
    • Use the decimal module for precise calculations when needed.
  2. Integer Division Difference

    • Be aware that / always returns a float, even if dividing two integers.
    print(10 / 2)   # Output: 5.0 (not int)
    
  3. Avoid Unnecessary Type Conversions

    • Converting between types excessively can lead to performance overhead.
    num = 10
    print(float(int(str(num))))  # Inefficient!
    
  4. Use math for Complex Computations

    • Instead of x ** 0.5, prefer math.sqrt(x) for better performance.

Conclusion

Numbers in Python are powerful, flexible, and behave like objects while being immutable. Whether you're performing simple calculations or handling complex numerical data, Python provides a wide range of tools to make it easy. Understanding number types, arithmetic operations, division nuances, and best practices ensures you write efficient and error-free code.

AUTHOR
PUBLISHED 7 February 2025
TOPICS