Numbers in Python

Numbers in Python

by David Amos Sep 16, 2020 basics python

You don’t need to be a math whiz to program well. The truth is, few programmers need to know more than basic algebra. Of course, how much math you need to know depends on the application you’re working on. In general, the level of math required to be a programmer is lower than you might expect. Although math and computer programming aren’t as correlated as some people might believe, numbers are an integral part of any programming language, and Python is no exception.

In this tutorial, you’ll learn how to:

  • Create integers and floating-point numbers
  • Round numbers to a given number of decimal places
  • Format and display numbers in strings

Let’s get started!

Integers and Floating-Point Numbers

Python has three built-in numeric data types: integers, floating-point numbers, and complex numbers. In this section, you’ll learn about integers and floating-point numbers, which are the two most commonly used number types. You’ll learn about complex numbers in a later section.

Integers

An integer is a whole number with no decimal places. For example, 1 is an integer, but 1.0 isn’t. The name for the integer data type is int, which you can see with type():

>>>
>>> type(1)
<class 'int'>

You can create an integer by typing the desired number. For instance, the following assigns the integer 25 to the variable num:

>>>
>>> num = 25

When you create an integer like this, the value 25 is called an integer literal because the integer is literally typed into the code.

You may already be familiar with how to convert a string containing an integer to a number using int(). For example, the following converts the string "25" to the integer 25:

>>>
>>> int("25")
25

int("25") is not an integer literal because the integer value is created from a string.

When you write large numbers by hand, you typically group digits into groups of three separated by a comma or a decimal point. The number 1,000,000 is a lot easier to read than 1000000.

In Python, you can’t use commas to group digits in integer literals, but you can use underscores (_). Both of the following are valid ways to represent the number one million as an integer literal:

>>>
>>> 1000000
1000000

>>> 1_000_000
1000000

There’s no limit to how large an integer can be, which might be surprising considering that computers have a finite amount of memory. Try typing the largest number you can think of into IDLE’s interactive window. Python can handle it with no problem!

Floating-Point Numbers

A floating-point number, or float for short, is a number with a decimal place. 1.0 is a floating-point number, as is -2.75. The name of the floating-point data type is float:

>>>
>>> type(1.0)
<class 'float'>

Like integers, floats can be created from floating-point literals or by converting a string to a float with float():

>>>
>>> float("1.25")
1.25

There are three ways to represent a floating-point literal. Each of the following creates a floating-point literal with a value of one million:

>>>
>>> 1000000.0
1000000.0

>>> 1_000_000.0
1000000.0

>>> 1e6
1000000.0

The first two ways are similar to the two techniques for creating integer literals. The third approach uses E notation to create a float literal.

To write a float literal in E notation, type a number followed by the letter e and then another number. Python takes the number to the left of the e and multiplies it by 10 raised to the power of the number after the e. So 1e6 is equivalent to 1×10⁶.

Python also uses E notation to display large floating-point numbers:

>>>
>>> 200000000000000000.0
2e+17

The float 200000000000000000.0 gets displayed as 2e+17. The + sign indicates that the exponent 17 is a positive number. You can also use negative numbers as the exponent:

>>>
>>> 1e-4
0.0001

The literal 1e-4 is interpreted as 10 raised to the power -4, which is 1/10000, or 0.0001.

Unlike integers, floats do have a maximum size. The maximum floating-point number depends on your system, but something like 2e400 ought to be well beyond most machines’ capabilities. 2e400 is 2×10⁴⁰⁰, which is far more than the total number of atoms in the universe!

When you reach the maximum floating-point number, Python returns a special float value, inf:

>>>
>>> 2e400
inf

inf stands for infinity, and it just means that the number you’ve tried to create is beyond the maximum floating-point value allowed on your computer. The type of inf is still float:

>>>
>>> n = 2e400
>>> n
inf
>>> type(n)
<class 'float'>

Python also uses -inf, which stands for negative infinity and represents a negative floating-point number that is beyond the minimum floating-point number allowed on your computer:

>>>
>>> -2e400
-inf

You probably won’t come across inf and -inf very often as a programmer unless you regularly work with extremely large numbers.

Check Your Understanding

Expand the block below to check your understanding:

Write a program that creates two variables, num1 and num2. Both num1 and num2 should be assigned the integer literal 25000000, one written with underscores and one without. Print num1 and num2 on two separate lines.

You can expand the block below to see a solution:

First, assign the value 25000000 to num1 without any underscores:

num1 = 25000000

Next, on a new line, assign the value 25_000_000 to the variable num2:

num2 = 25_000_000

Print both variables on separate lines by passing each variable to separate calls of print():

print(num1)
print(num2)

In the output, you can see that both numbers are the same:

25000000
25000000

Although both variables are assigned the value 25000000, writing the value using underscores to group digits makes it much easier for a human to quickly work out what the number is. No more squinting at the screen and trying to count zeros!

When you’re ready, you can move on to the next section.

Arithmetic Operators and Expressions

In this section, you’ll learn how to do basic arithmetic, such as addition, subtraction, multiplication, and division, with numbers in Python. Along the way, you’ll learn some conventions for writing mathematical expressions in code.

Addition

Addition is performed with the + operator:

>>>
>>> 1 + 2
3

The two numbers on either side of the + operator are called operands. In the above example, both operands are integers, but operands don’t need to be the same type.

You can add an int to a float with no problem:

>>>
>>> 1.0 + 2
3.0

Notice that the result of 1.0 + 2 is 3.0, which is a float. Anytime a float is added to a number, the result is another float. Adding two integers together always results in an int.

Subtraction

To subtract two numbers, just put a - operator between them:

>>>
>>> 1 - 1
0

>>> 5.0 - 3
2.0

Just like adding two integers, subtracting two integers always results in an int. Whenever one of the operands is a float, the result is also a float.

The - operator is also used to denote negative numbers:

>>>
>>> -3
-3

You can subtract a negative number from another number, but as you can see below, this can sometimes look confusing:

>>>
>>> 1 - -3
4

>>> 1 --3
4

>>> 1- -3
4

>>> 1--3
4

Of the four examples above, the first is the most PEP 8 compliant. That said, you can surround -3 with parentheses to make it even clearer that the second - is modifying 3:

>>>
>>> 1 - (-3)
4

Using parentheses is a good idea because it makes your code more explicit. Computers execute code, but humans read code. Anything you can do to make your code easier to read and understand is a good thing.

Multiplication

To multiply two numbers, use the * operator:

>>>
>>> 3 * 3
9

>>> 2 * 8.0
16.0

The type of number you get from multiplication follows the same rules as addition and subtraction. Multiplying two integers results in an int, and multiplying a number with a float results in a float.

Division

The / operator is used to divide two numbers:

>>>
>>> 9 / 3
3.0

>>> 5.0 / 2
2.5

Unlike addition, subtraction, and multiplication, division with the / operator always returns a float. If you want to make sure that you get an integer after dividing two numbers, you can use int() to convert the result:

>>>
>>> int(9 / 3)
3

Keep in mind that int() discards any fractional part of the number:

>>>
>>> int(5.0 / 2)
2

5.0 / 2 returns the floating-point number 2.5, and int(2.5) returns the integer 2 with the .5 removed.

Integer Division

If writing int(5.0 / 2) seems a little long winded to you, Python provides a second division operator called the integer division operator (//), also known as the floor division operator:

>>>
>>> 9 // 3
3

>>> 5.0 // 2
2.0

>>> -3 // 2
-2

The // operator first divides the number on the left by the number on the right and then rounds down to an integer. This might not give the value you expect when one of the numbers is negative.

For example, -3 // 2 returns -2. First, -3 is divided by 2 to get -1.5. Then -1.5 is rounded down to -2. On the other hand, 3 // 2 returns 1 because both numbers are positive.

The above example also illustrates that // returns a floating-point number when one of the operands is a float. This is why 9 // 3 returns the integer 3, and 5.0 // 2 returns the float 2.0.

Let’s see what happens when you try to divide a number by 0:

>>>
>>> 1 / 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

Python gives you a ZeroDivisionError, letting you know that you just tried to break a fundamental rule of the universe.

Exponents

You can raise a number to a power using the ** operator:

>>>
>>> 2 ** 2
4

>>> 2 ** 3
8

>>> 2 ** 4
16

Exponents don’t have to be integers. They can also be floats:

>>>
>>> 3 ** 1.5
5.196152422706632

>>> 9 ** 0.5
3.0

Raising a number to the power of 0.5 is the same as taking the square root, but notice that even though the square root of 9 is an integer, Python returns the float 3.0.

For positive operands, the ** operator returns an int if both operands are integers and a float if any one of the operands is a floating-point number.

You can also raise numbers to negative powers:

>>>
>>> 2 ** -1
0.5

>>> 2 ** -2
0.25

Raising a number to a negative power is the same as dividing 1 by the number raised to the positive power. So, 2 ** -1 is the same as 1 / (2 ** 1), which is the same as 1 / 2, or 0.5. Similarly, 2 ** -2 is the same as 1 / (2 ** 2), which is the same as 1 / 4, or 0.25.

The Modulus Operator

The % operator, or the modulus, returns the remainder of dividing the left operand by the right operand:

>>>
>>> 5 % 3
2

>>> 20 % 7
6

>>> 16 % 8
0

3 divides 5 once with a remainder of 2, so 5 % 3 is 2. Similarly, 7 divides 20 twice with a remainder of 6. In the last example, 16 is divisible by 8, so 16 % 8 is 0. Anytime the number to the left of % is divisible by the number to the right, the result is 0.

One of the most common uses of % is to determine whether one number is divisible by another. For example, a number n is even if and only if n % 2 is 0. What do you think 1 % 0 returns? Let’s try it out:

>>>
>>> 1 % 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

This makes sense because 1 % 0 gives the remainder of dividing 1 by 0. But you can’t divide 1 by 0, so Python raises a ZeroDivisionError.

Things get a little tricky when you use the % operator with negative numbers:

>>>
>>> 5 % -3
-1

>>> -5 % 3
1

>>> -5 % -3
-2

Although potentially shocking at first glance, these results are the product of a well-defined behavior in Python. To calculate the remainder r of dividing a number x by a number y, Python uses the equation r = x - (y * (x // y)).

For example, to find 5 % -3, Python first finds (5 // -3). Since 5 / -3 is about -1.67, that means 5 // -3 is -2. Now Python multiplies that by -3 to get 6. Finally, Python subtracts 6 from 5 to get -1.

Arithmetic Expressions

You can combine operators to form complex expressions. An expression is a combination of numbers, operators, and parentheses that Python can compute, or evaluate, to return a value.

Here are some examples of arithmetic expressions:

>>>
>>> 2*3 - 1
5

>>> 4/2 + 2**3
10.0

>>> -1 + (-3*2 + 4)
-3

The rules for evaluating expressions are the same as in everyday arithmetic. In school, you probably learned these rules under the name order of operations.

The *, /, //, and % operators all have equal precedence, or priority, in an expression, and each of these has a higher precedence than the + and - operators. This is why 2*3 - 1 returns 5 and not 4. 2*3 is evaluated first, because * has higher precedence than the - operator.

You may notice that the expressions in the previous example do not follow the rule for putting a space on either side of all of the operators. PEP 8 says the following about whitespace in complex expressions:

If operators with different priorities are used, consider adding whitespace around the operators with the lowest priority(ies). Use your own judgment; however, never use more than one space, and always have the same amount of whitespace on both sides of a binary operator. (Source)

Another good practice is to use parentheses to indicate the order in which operations should be performed, even if the parentheses aren’t necessary. For instance, (2 * 3) - 1 is potentially clearer than 2*3 - 1.

Make Python Lie to You

What do you think 0.1 + 0.2 is? The answer is 0.3, right? Let’s see what Python has to say about it. Try this out in the interactive window:

>>>
>>> 0.1 + 0.2
0.30000000000000004

Well, that’s . . . almost right. What in the heck is going on here? Is this a bug in Python?

No, it’s not a bug! It’s a floating-point representation error, and it has nothing to do with Python. It’s related to the way floating-point numbers are stored in a computer’s memory.

The number 0.1 can be represented as the fraction 1/10. Both the number 0.1 and its fraction 1/10 are decimal representations, or base-10 representations. Computers, however, store floating-point numbers in base-2 representation, more commonly called binary representation.

When represented in binary, something familiar yet possibly unexpected happens to the decimal number 0.1. The fraction 1/3 has no finite decimal representation. That is, 1/3 = 0.3333... with infinitely many 3s after the decimal point. The same thing happens to the fraction 1/10 in binary.

The binary representation of 1/10 is the following infinitely repeating fraction:

0.00011001100110011001100110011...

Computers have finite memory, so the number 0.1 must be stored as an approximation and not as its true value. The approximation that gets stored is slightly higher than the actual value and looks like this:

0.1000000000000000055511151231257827021181583404541015625

You may have noticed, however, that when asked to print 0.1, Python prints 0.1 and not the approximated value above:

>>>
>>> 0.1
0.1

Python doesn’t just chop off the digits in the binary representation for 0.1. What actually happens is a little more subtle.

Because the approximation of 0.1 in binary is just that—an approximation—it’s entirely possible that more than one decimal number has the same binary approximation.

For example, both 0.1 and 0.10000000000000001 have the same binary approximation. Python prints out the shortest decimal number that shares the approximation.

This explains why, in the first example of this section, 0.1 + 0.2 doesn’t equal 0.3. Python adds together the binary approximations for 0.1 and 0.2, which gives a number that is not the binary approximation for 0.3.

If all this is starting to make your head spin, don’t worry! Unless you’re writing programs for finance or scientific computing, you don’t need to worry about the imprecision of floating-point arithmetic.

Math Functions and Number Methods

Python has a few built-in functions that you can use to work with numbers. In this section, you’ll learn about three of the most common:

  1. round(), for rounding numbers to some number of decimal places
  2. abs(), for getting the absolute value of a number
  3. pow(), for raising a number to some power

You’ll also learn about a method you can use with floating-point numbers to check whether they have an integer value.

Round Numbers With round()

You can use round() to round a number to the nearest integer:

>>>
>>> round(2.3)
2

>>> round(2.7)
3

round() has some unexpected behavior when the number ends in .5:

>>>
>>> round(2.5)
2

>>> round(3.5)
4

2.5 is rounded down to 2, and 3.5 is rounded up to 4. Most people expect a number that ends in .5 to be rounded up, so let’s take a closer look at what’s going on here.

Python 3 rounds numbers according to a strategy called rounding ties to even. A tie is any number whose last digit is five. 2.5 and 3.1415 are ties, but 1.37 is not.

When you round ties to even, you first look at the digit one decimal place to the left of the last digit in the tie. If that digit is even, then you round down. If the digit is odd, then you round up. That’s why 2.5 rounds down to 2 and 3.5 rounds up to 4.

You can round a number to a given number of decimal places by passing a second argument to round():

>>>
>>> round(3.14159, 3)
3.142

>>> round(2.71828, 2)
2.72

The number 3.14159 is rounded to three decimal places to get 3.142, and the number 2.71828 is rounded to two decimal places to get 2.72.

The second argument of round() must be an integer. If it isn’t, then Python raises a TypeError:

>>>
>>> round(2.65, 1.4)
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    round(2.65, 1.4)
TypeError: 'float' object cannot be interpreted as an integer

Sometimes round() doesn’t get the answer quite right:

>>>
>>> # Expected value: 2.68
>>> round(2.675, 2)
2.67

2.675 is a tie because it lies exactly halfway between the numbers 2.67 and 2.68. Since Python rounds ties to the nearest even number, you would expect round(2.675, 2) to return 2.68, but it returns 2.67 instead. This error is the result of a floating-point representation error, not a bug in round().

Dealing with floating-point numbers can be frustrating, but this frustration isn’t specific to Python. All languages that implement the IEEE floating-point standard have the same issues, including C/C++, Java, and JavaScript.

In most cases, though, the little errors encountered with floating-point numbers are negligible, and the results of round() are perfectly useful.

Find the Absolute Value With abs()

The absolute value of a number n is just n if n is positive and -n if n is negative. For example, the absolute value of 3 is 3, while the absolute value of -5 is 5.

To get the absolute value of a number in Python, you use abs():

>>>
>>> abs(3)
3

>>> abs(-5.0)
5.0

abs() always returns a positive number of the same type as its argument. That is, the absolute value of an integer is always a positive integer, and the absolute value of a float is always a positive float.

Raise to a Power With pow()

Earlier, you learned how to raise a number to a power using the ** operator. You can also use pow() to achieve the same result.

pow() takes two arguments. The first argument is the base, or the number to be raised to a power, and the second argument is the exponent, or the power to which the number is to be raised.

For example, the following uses pow() to raise 2 to the exponent 3:

>>>
>>> pow(2, 3)
8

Just like with **, the exponent in pow() can be negative:

>>>
>>> pow(2, -2)
0.25

So, what’s the difference between ** and pow()?

The pow() function accepts an optional third argument that computes the first number raised to the power of the second number, then takes the modulo with respect to the third number. In other words, pow(x, y, z) is equivalent to (x ** y) % z.

Here’s an example in which x = 2, y = 3, and z = 2:

>>>
>>> pow(2, 3, 2)
0

First, 2 is raised to the power 3 to get 8. Then 8 % 2 is calculated, which is 0 because 2 divides 8 with no remainder.

Check if a Float Is Integral

You may be familiar with string methods like .lower(), .upper(), and .find(). Integers and floating-point numbers also have methods.

Number methods aren’t used very often, but there is one that can be useful. Floating-point numbers have an .is_integer() method that returns True if the number is integral—meaning it has no fractional part—and otherwise returns False:

>>>
>>> num = 2.5
>>> num.is_integer()
False

>>> num = 2.0
>>> num.is_integer()
True

One use for .is_integer() is for validating user input. For example, if you were writing an online ordering app for a pizzeria, then you would want to check that the quantity of pizzas the customer inputs is a whole number.

The round(), abs(), and pow() functions are built-in functions, meaning you don’t have to import anything in order to use them. But these three functions barely scratch the surface of all of the functions available for working with numbers in Python.

For even more math fun, check out The Python math Module: Everything You Need to Know!

Check Your Understanding

Expand the block below to check your understanding:

Write a program that asks the user to input a number and then displays that number rounded to two decimal places. When run, your program should look like this:

Enter a number: 5.432
5.432 rounded to 2 decimal places is 5.43

You can expand the block below to see a solution:

To get input from a user, pass the prompt to input():

user_input = input("Enter a number: ")

Notice the space at the end of the prompt string. This ensures there’s a space between the text entered by the user when they start typing and the colon in the prompt.

The value returned by input() is a string, so you need to convert it to a float before you can round the number:

num = float(user_input)

Keep in mind that the above code assumes that the string user_input really does contain a numerical value and not any other kind of text.

Now you can use round() to round the value to two decimal places:

rounded_num = round(num, 2)

Remember, the first argument to round() should be the number to be rounded. The second argument is the number of decimal places to round to.

Finally, you can print the ouput by inserting rounded_num into an f-string:

print(f"{num} rounded to 2 decimal places is {rounded_num}")

round() is a great way to round values, but if you’re only rounding values in order to display them, then you might consider using the techniques described in the following section.

When you’re ready, you can move on to the next section.

Complex Numbers

Python is one of the few programming languages that provides built-in support for complex numbers. While complex numbers don’t often come up outside the domains of scientific computing and computer graphics, Python’s support for them is one of its strengths.

If you’ve ever taken a precalculus or higher-level algebra math class, then you may remember that a complex number is a number with two distinct components: a real part and an imaginary part.

To create a complex number in Python, you simply write the real part, then a plus sign, then the imaginary part with the letter j at the end:

>>>
>>> n = 1 + 2j

When you inspect the value of n, you’ll notice that Python wraps the number with parentheses:

>>>
>>> n
(1+2j)

This convention helps eliminate any confusion that the displayed output may represent a string or a mathematical expression.

Imaginary numbers come with two properties, .real and .imag, that return the real and imaginary components of the number, respectively:

>>>
>>> n.real
1.0

>>> n.imag
2.0

Notice that Python returns both the real and imaginary components as floats, even though they were specified as integers.

Complex numbers also have a .conjugate() method that returns the complex conjugate of the number:

>>>
>>> n.conjugate()
(1-2j)

For any complex number, its conjugate is the complex number with the same real part and an imaginary part that is the same in absolute value but with the opposite sign. So in this case, the complex conjugate of 1 + 2j is 1 - 2j.

Except for the floor division operator (//), all the arithmetic operators that work with floats and integers will also work with complex numbers. Since this isn’t an advanced math tutorial, we won’t discuss the mechanics of complex arithmetic. Instead, here are some examples of using complex numbers with arithmetic operators:

>>>
>>> a = 1 + 2j
>>> b = 3 - 4j

>>> a + b
(4-2j)

>>> a - b
(-2+6j)

>>> a * b
(11+2j)

>>> a ** b
(932.1391946432212+95.9465336603415j)

>>> a / b
(-0.2+0.4j)

>>> a // b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't take floor of complex number.

Interestingly, although not surprising from a mathematical point of view, int and float objects also have .real and .imag properties as well as the .conjugate() method:

>>>
>>> x = 42
>>> x.real
42
>>> x.imag
0
>>> x.conjugate()
42

>>> y = 3.14
>>> y.real
3.14
>>> y.imag
0.0
>>> y.conjugate()
3.14

For floats and integers, .real and .conjugate() always return the number itself, and .imag always returns 0. One thing to notice, however, is that n.real and n.imag return an integer if n is an integer and a float if n is a float.

Now that you’ve seen the basics of complex numbers, you might be wondering when you would ever need to use them. If you’re learning Python for web development, data science, or general-purpose programming, the truth is that you may never need to use complex numbers.

On the other hand, complex numbers are important in domains such as scientific computing and computer graphics. If you ever work in those domains, then you may find Python’s built-in support for complex numbers useful.

Conclusion: Numbers in Python

In this tutorial, you learned all about working with numbers in Python. You saw that there are two basic types of numbers—integers and floating-point numbers—and that Python also has built-in support for complex numbers.

In this tutorial, you learned:

  • How to do basic arithmetic with numbers using Python’s aritmetic operators
  • How to write arithmetic expressions using PEP 8 best practices
  • What floating-point numbers are and why they may not always be 100 percent accurate
  • How to round numbers with round()
  • What complex numbers are and how they’re supported in Python

No matter your comfort level with numbers and math, you’re now ready to perform all kinds of calculations in your Python code. You can use this knowledge to solve a wide range of problems that you’ll encounter in your programming career.

Further Reading

For additional information on numbers and math in Python, check out these resources:

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

About David Amos

David Amos David Amos

David is a mathematician by training, a data scientist/Python developer by profession, and a coffee junkie by choice.

» More about David

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

Master Real-World Python Skills With Unlimited Access to Real Python

Join us and get access to hundreds of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

Master Real-World Python Skills
With Unlimited Access to Real Python

Join us and get access to hundreds of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Real Python Comment Policy: The most useful comments are those written with the goal of learning from or helping out other readers—after reading the whole article and all the earlier comments. Complaints and insults generally won’t make the cut here.

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Keep Learning

Related Tutorial Categories: basics python