# The Basics of Numbers in Python

## Numeric Data Types in Python

Python supports several numeric data types, including integers, floating-point, and complex numbers. Each one holds unique characteristics and caveats. So, it's advisable to specifically deepen your knowledge, depending on the path you choose to pursue in the language.

Practically speaking, each time we assign a numeric value to a variable, a number object is created to store that value. Since they're immutable by nature, changing the value will result in a newly created object.

## Integers

Except for fractions, integers consist of positive and negative whole numbers as well as zero. As we mentioned earlier, integer variables or literals are part of the `int` class as seen in the example below.

Integers have numerous use cases and they can represent counts, such as the number of items in a list or the number of times a loop runs, just to name a few.

``````# Assign an integer value to a variable
x = 42

y = -7

z = 1_000_000

# Print the type of the variable
print(type(x))
print(type(y))
print(type(z))
``````

The output of each type check:

``````# Output: <class 'int'>
``````

Note: We can delimit integers by using an underscore `_`

Python integers have virtually unlimited size, despite the limitations of our computer memory. They may potentially find use in applications such as cryptography and scientific calculations, even though working with enormous ones can impact performance and extra optimization of the code will have to take place.

## Floats

Floating-point numbers or floats consist of all positive and negative, real numbers including their fractional part. We can neatly utilize them in our code for specific measurements or currency values. To denote them, we use the decimal symbol `.` or in some cases the scientific(exponential) notation, written with `e` or `E`.

Floating-point numbers can be created directly by entering a number with a decimal point or by performing operations such as division with integers. Moreover, Python automatically ignores any extra zeros at the end of a number.

``````# Assign a floating-point value to a variable
x = 3.14

# Print the type of the variable
print(type(x)) # Output: <class 'float'>

# Additional example of a floating-point number
y = -7.823457

# Example of a floating-point number in scientific notation
z = 1.23e-4

# Division of integers resulting in a floating-point number
a = 5 / 2
print(a) # Output: 2.5
``````

Now, some floating-point arithmetic is subject to rounding errors, due to the way that computers represent decimal values internally. They can sometimes lead to unexpected results, as this one below:

``````print(1.1 + 2.2) # Output: 3.3000000000000003
``````

To mitigate these issues, we recommend using the decimal module when precision is critical.

## Complex Numbers

If you're oriented to learning the ropes of web development or data science with Python, you'll rarely come across complex numbers. They find use in scientific computing and graphics applications, which usually rely on libraries that ease the process.

Complex numbers comprise two separate parts; real and imaginary.

``````# 3 represents the real part, and 4 multiplied by j represents the imaginary
x = 3 + 4j

# Print the type of the variable
print(type(x)) # Output: <class 'complex'>
``````

## Built-in Number Methods

We can work with numbers by leveraging numerous built-in methods that Python offers. Let's demonstrate how we can round a float to a specified number of decimal places with the `round()` method:

``````# Round a floating-point number to a specified number of decimal places
x = 3.14159
print(round(x, 2)) # Output: 3.14
``````

Or, how the `abs()` method finds the absolute value of a number:

``````# Find the absolute value of a number
x = -42
print(abs(x)) # Output: 42
``````

Lastly, let's observe how to raise a number to a specified power with the `pow()` method:

``````# Raise a number to a specified power
x = 2
print(pow(x, 3)) # Output: 8
``````

In addition to these built-in methods, the math module gives us the option to perform a variety of mathematical functions. For instance, we can use the `math.sqrt()` function to find the square root of a number:

``````import math

# Find the square root of a number
x = 16
print(math.sqrt(x)) # Output: 4.0
``````

## Number Type Conversion and Caveats

In some cases, we may need to convert a number from one type to another. That might include converting a float to an integer or vice versa.

``````# Convert a float to an integer
x = 3.14
print(int(x)) # Output: 3
``````

We can also do the opposite:

``````# Convert an integer to a float
x = 42
print(float(x)) # Output: 42.0
``````

Bear in mind that converting a float to an integer truncates the decimal part of the number while changing an integer to a float may result in a loss of precision.

Some conversions in Python are simply not possible and may result in errors. Such is the case with complex numbers as they cannot be converted to other number types. Moreover, we can't convert a string representation of a number to a complex number or vice versa.

``````# Attempt to convert a string to a complex number
x = "3 + 4j"
print(complex(x)) # ValueError: complex() arg is a malformed string
``````

## Final Thoughts

Numbers play a significant role in the world of programming. In this overview, we've delved into the numeric data types in Python, including integers, floats, and complex numbers, as well as the built-in functions and methods for working with numbers.

As we continue our journey into the world of Python programming, we'll be covering other data types as well as a variety of other essential concepts.

Feel free to check out some of the additional resources below.