## Introduction

**Numbers** are a fundamental aspect of computer programming. Python provides robust support for numeric operations and data types. This lesson covers the three built-in **numeric types** available in Python: **integers**, **floating-point** numbers, and **complex numbers**.

## Integers

An integer is a whole number that can be written without a fractional or decimal component. They can be positive, negative, or zero, such as -2, -1, 0, 1, 2.

In Python, integers are represented by the `int`

type. Python `int`

literals are written then same way as integers are in common language, i.e. a sequence of digits, with a minus sign on the left to represent a negative number.

**Example:**

positive_integer = 10 negative_integer = -5 zero = 0

Python’s `int`

type can handle arbitrarily large integers. Unlike some other programming languages that have a fixed maximum size for integers, Python’s integers grow as needed to accommodate the value.

**Example:**

very_large_integer = 500000000000000000000000000000000000000000000000000

## Floating Point Numbers

Floating-point numbers, often abbreviated as floats, are numbers that contain a decimal point. The floating-point type in Python is `float`

.

Float literals are written in Python as either a decimal fraction, a scientific notation, or both.

**Example:**

approx_pi = 3.14 some_float = 10e4 another_float = 6.022e23

Python implements floating-point numbers according to the IEEE 754 standard, which defines the format for representing both floating-point numbers and their arithmetic operations. This standard allows Python to maintain consistency in floating-point operations across different platforms and architectures.

### Precision Problems With Floats

Although floating-point numbers are essential for representing a wide range of real numbers, they have limitations due to their finite precision. This limitation can lead to problems where calculations may not produce the expected results due to rounding errors.

Floating point numbers are represented in computer memory with a finite sequence of digits. Consequently, they cannot precisely represent numbers that require an infinite sequence. The numbers that floats can’t represent not only include irrational numbers (that require infinite non-repeating sequences of digits) such as Pi, but also rational numbers that require infinite repeating sequences, such as 1/3, which is represented in decimal by 0.333…

However, since digital computers are based on the binary system (1’s and 0’s), the rational numbers that require an infinite repeating sequence of digits are not necessarily the same ones we are used to. For example, multiples of one tenth in decimal (0.1) need an infinite sequences of digits in binary, which leads to unexpected behaviors.

**Example:**

print(0.1 + 0.2)

**Output:**

0.30000000000000004

In the example above, the floating-point numbers 0.1 and 0.2 are added, and seemingly the result of this addition is a small amount more than 0.3. This happens because it’s not really 0.1 and 0.2 that are added, but the imprecise, truncated versions of their binary representations. When the truncated numbers are added in binary and converted to decimal for printing, the result is not exactly 0.3 due to rounding errors.

## Complex Numbers

A complex number is a number that has both a real part and an imaginary part, typically expressed in the form *a* + *b***j**, where *a* is the real part, *b* is the imaginary part, and **j** (or **i** in mathematics) is the imaginary unit with the property that j^{2} = -1.

Complex numbers are represented in Python by the `complex`

type. Python uses `j`

to denote the imaginary part of a complex number literal.

### Declaring and Using Complex Numbers

Declaring a complex number in Python is straightforward. You can use the `complex()`

function or the literal notation with `j`

.

Here is the basic syntax for declaring a complex number using the `complex()`

function:

z = complex(real, imag)

And this is how you can declare a complex number literal with `j`

:

z = real + imagj

In this syntax:

**real**: The real part of the complex number. This part must be an integer or float literal. It*can*be omitted, in which case the real part is set to 0.**imag**: The imaginary part of the complex number. This part must also be an integer or float literal.

**Example:**

z1 = complex(2, 3) z2 = 2 + 3j z3 = 0.5 + 2.1j

## Underscores In Numbers

Sequences of digits in numeric literals can have underscores in between the digits. Python ignores those underscores, and they function as an optional way to improve the readability of long numbers in source code. They are similar in purpose to commas that are placed after every third digit in written language.

The Python `print()`

function and terminal clear out the underscores.

**Example:**

print(50_000_000_000_000)

**Output:**

50000000000000

## Arithmetic Operations

Python provides a variety of arithmetic operations that can be performed on numeric types using operators. Here are some of the most commonly used operators:

**Addition (**: Adds two numbers.`+`

)**Subtraction (**: Subtracts one number from another.`-`

)**Multiplication (**: Multiplies two numbers.`*`

)**Division (**: Divides one number by another and returns a float.`/`

)**Floor Division (**: Divides one number by another and returns an integer.`//`

)**Modulus (**: Returns the remainder of the division.`%`

)**Exponentiation (**: Raises a number to the power of another.`**`

)

**Examples:**

a = 10 b = 3 print(a + b) # Output: 13 print(a - b) # Output: 7 print(a * b) # Output: 30 print(a / b) # Output: 3.3333333333333335 print(a // b) # Output: 3 print(a % b) # Output: 1 print(a ** b) # Output: 1000

All the arithmetic operators work on `int`

and `float`

types. They also work on `complex`

numbers except for `//`

and `%`

.

If you use an operator with two of the same numeric type, the result is of that type, except for `/`

, which results in a `float`

when two `int`

s are divided. `//`

division will result in an `int`

.

You can use operators with two different numeric types. If one of the operands is a `float`

the result is a float, unless one is `complex`

, which results in a `complex`

type.

## Summary & Reference for Python Numbers

Python provides robust support for numeric operations with floating-point, and complex numbers data types.

Integers such as -2, -1, 0, 1, and 2 are represented in Python by the `int`

type.

positive_integer = 10 negative_integer = -5 zero = 0

Python’s `int`

type can handle arbitrarily large integers.

very_large_integer = 500000000000000000000000000000000000000000000000000

Floating-point numbers (floats), are numbers that contain a decimal point, and are represented in Python by the `float`

type.

approx_pi = 3.14 some_float = 10e4 another_float = 6.022e23

Floats hold a limited number of binary digits and therefore cannot represent all real numbers precisely, leading to unexpected results.

0.1 + 0.2 # --> 0.30000000000000004

Complex numbers have both a real and an imaginary part, and are represented in Python by the `complex`

type. Python literals are written with the `j`

notation for the imaginary part.

z = 2 + 3.5j

You can also create a complex number using the `complex()`

function.

complex(2, 3.5) # --> 2+3.5j

Sequences of digits in numeric literals can have underscores in between the digits. Those can be used to improve the readability of long numbers in source code.

print(50_000_000_000_000) # --> 50000000000000

Python provides a variety of arithmetic operators that can be used on numeric types. Those include addition (`+`

), subtraction (`-`

), multiplication (`*`

), division (`/`

), floor division (`//`

), modulus (`%`

), and exponentiation (`**`

).

1.1 + 2.2 # --> 3.3

All the arithmetic operators work on `int`

and `float`

types. They also work on `complex`

numbers except for `//`

and `%`

.