Quantcast
Channel: Like Geeks
Viewing all articles
Browse latest Browse all 104

A Foolproof Guide to Infinity In Python

$
0
0

Numbers are an integral part of programming. Hence, programming languages support various datatypes to represent different kinds of numbers and provide various methods to work with them.
Each of these datatypes comes with certain limitations on the range of numbers they can represent; while some can represent a small range of numbers, others support a very large range of numbers. Depending on our use case, we can choose from one of them.
But none of them have a way to represent infinity.

We often encounter and have to deal with infinity in many real-world scenarios, and so we need a way to represent them in programming languages.
In this tutorial, we’ll learn how to represent and work with infinity in Python.

 

What is Infinity?

Before diving into the programming know-how of working with infinity, let us first understand what infinity is, by formally defining it

There are dozens of definitions of infinity depending on its usage in different contexts and domains. We’ll focus on the ones that are used in mathematics and computing.
Infinity is defined as a large, ‘undefined’ number that is bigger than any real number.
It exists on both ends of the number line, and hence we have both positive and negative infinities.
Infinity is denoted using the symbol ∞.

In Computer Science, it is also defined as a result of an ‘undefined operation’ such as division by zero. In programming, infinity is used to define an absolute max/min value in algorithms defined for optimizations.
For eg. in algorithms for finding the shortest path between two nodes of a graph, the initial value for shortest_path_distance can be set to infinity.

 

Declaring Infinity

There exist a number of different ways to represent infinity in Python. Let us look at a few of them.

We can declare infinity as a floating-point number, by passing the string value ‘inf’ or ‘infinity’ to the method float.

a = float("inf")

print(f"value of a = {a}")

print(f"type of a = {type(a)}")

Output:

using float to declare infinity

As we discussed, there also exists ‘negative infinity’. We can declare the same by passing ‘-inf’, or by creating positive infinity, and prefixing it with ‘-‘ sign.

b = float("-inf")

print(f"value of b = {b}")

print(f"value of -float('inf') = {-float('inf')}")

Output:

using float to declare negative infinity

Note that the string that we pass to the float method is case-independent. So passing “INF” or “inFINIty” would also be correctly evaluated to inf.

We can also use Python’s math module to represent infinity.
The module has predefined value math.inf that can be assigned to variables to represent infinity.

import math

c = math.inf

d = -math.inf #negative inf

print(f"value of c is {c}")

print(f"value of d is {d}")

print(f"type of c = {type(c)}")

Output:

using math module to declare infinity

It turns out the math module also defines infinity as a floating-point number and apparently, the infinities declared by the two methods are equivalent.
Let’s check it out.

float_inf = float("inf")

math_inf = math.inf

print(f"float_inf == math.inf is {float_inf == math.inf}")

Output:

comparing infinities of float and math

So these were just two different ways of representing the same value i.e inf.

 

Why the infinity is float type?

You must be wondering why the infinity is not int type, and if it’s an undefined number how does its datatype matter?

The answer lies in the way the numbers are represented in Python.
An integer number is represented using its binary representation, for eg. 5 is represented as 0101.
The floating-point numbers, on the other hand, are represented using 3 components – sign, mantissa, and exponent. This is as per the IEEE 754 standard for storing floating-point numbers.

The IEEE 754 standard reserves some values to represent special numbers. One of these special numbers is infinity.
According to this standard, a floating-point number represents an infinity when all the bits in the exponent part are 1, and all the bits in the mantissa part are 0.
Additionally, if the sign bit is 0, it is positive infinity, while a 1 in the sign bit denotes a negative infinity.

So, since infinity is a special value that cannot be represented using simple binary representation, hence its datatype is float in Python.

 

Arithmetic Operations on infinity

Since infinity is a floating-point number, we can perform various arithmetic operations on it, and the results of such operations are also defined by the IEEE standard.

Addition

If we add any finite real number to infinity, the result will be infinity.
If we add infinity to infinity, the result will again be an infinity.
However, if we add a negative infinity to positive infinity, the result will be undefined or NaN (Not a Number). NaN is another special number like infinity that is represented in Python using float datatype, as per IEEE 754 standard.

inf = float("infinity")

print(f"inf + 100  = {inf + 100}")

print(f"inf + 0.52  = {inf + 0.52}")

print(f"inf + inf  = {inf + inf}")

print(f"-inf + inf  = {-inf + inf}")

Output:

addition operations on infinity

Subtraction

Subtracting a positive, real number from infinity yields infinity.
Subtracting infinity from any positive, real number returns negative infinity.
Subtracting infinity from infinity results in an undefined result i.e NaN (as was observed in the previous section).
Subtracting infinity from negative infinity gives negative infinity.

print(f"inf - 50 = {inf - 50}")

print(f"299.9 - inf = {299.9 - inf}")

print(f"inf - inf = {inf - inf}")

print(f"-inf - inf = {-inf - inf}")

Output:

subtraction operations on infinity

Multiplication

The multiplication of any positive number with infinity gives infinity as the result.
Multiplying infinity by another infinity also results in infinity.
Multiplying infinity by zero is undefined, it returns NaN.
Multiplying infinity by negative infinity, or any negative number, yields negative infinity.

print(f"inf * 1000 = {inf * 1000}")
    
print(f"inf * inf = {inf * inf}")

print(f"inf * (-inf) = {inf * (-inf)}")

print(f"inf * 0 = {inf * 0}")

print(f"inf * 0.5 = {inf * 0.5}")

Output:

multiplication operations on infinity

Division

Dividing infinity by any positive or negative number returns positive or negative infinity, respectively.
Dividing infinity by itself, or by negative infinity returns a NaN.
Dividing any finite number by infinity results in 0 or −0.

Finally, dividing infinity by 0 results in ‘ZeroDivisonError’

print(f"inf / 20 = {inf / 20}")

print(f"-inf / 34 = {-inf / 34}")

print(f"inf / inf = {inf / inf}")

print(f"inf / -inf = {inf / -inf}")

print(f"99 / -inf = {99 / -inf}")

print(f"0 / inf = {0 / inf}")

Output:

division operations on infinity

Note that while doing the decimal division of infinity by any number results in infinity; doing floor division, however, results in NaN.

print(f"inf // 20 = {inf // 20}")

Output:

floor division on infinity

Modulo operation

The modulo operation on two numbers returns the remainder when integer division is performed between the two.

The behavior of modulo operation on infinity is a bit weird.
While modulo of infinity(both positive & negative) with any number (positive, negative, infinity) yields NaN, modulo of a real number with +infinity, however, returns that number.
Modulo of real number with -infinity, on the other hand, gives -infinity as the result.

print(f" 67 % 5 = {67 % 5}")

print(f"inf % 20 = {inf % 20}")

print(f"-inf % 34 = {-inf % 34}")

print(f"inf % inf = {inf % inf}")

print(f"inf % -inf = {inf % -inf}")

print(f"99 % inf = {99 % inf}")

print(f"99 % -inf = {99 % -inf}")

print(f"0 % inf = {0 % inf}")

Output:

modulo operation on real and infinity

 

NumPy infinity

In addition to the math module, and the float method, an infinity can also be assigned using NumPy‘s np.inf constant.

NumPy also follows IEEE 754 standard for storing floating-point numbers, and so the value of np.inf is equal to float("inf") and math.inf. The datatype of np.inf is also float.

NumPy’s infinity constant can also be accessed using several aliases such as np.Infinitynp.Inf, and np.infty.
NumPy also defines separate constants for positive and negative infinities. Positive infinity can be accessed using np.PINF (alias for np.inf), and the negative infinity can be accessed using the constant np.NINF.

import numpy as np

import math

a = np.inf

print(f"value of a = {a}")

print(f"np.inf == float('Infinity') evaluates to {np.inf == float('Infinity')}")

print(f"np.inf == math.inf evaluates to {np.inf == math.inf}")

print(f"dataype of np.inf is {type(np.inf)}")

print(f"np.PINF evaluates to {np.PINF}")

print(f"np.NINF evaluates to {np.NINF}")

print(f"np.PINF is np.inf evaluates to {np.PINF is np.inf}") #alias check

Output:

basic usages of NumPy infinity

NumPy also has methods to find out whether a value is an infinity or not. It also has separate methods to check if the value is positive or negative infinity.

b = np.inf

print(f"b = {b}")

print(f"np.isinf(b): {np.isinf(b)}")

print(f"np.isposinf(b): {np.isposinf(b)}")

print(f"np.isneginf(b): {np.isneginf(b)}")

c = np.NINF

print(f"\nc = {c}")

print(f"np.isneginf(c): {np.isneginf(c)}")

Output:

NumPy method to check infinity

Note that we can also pass NumPy arrays to these methods; it will return an array of boolean values, denoting positions in the array where the value is infinity.

x = np.array([1,8, float("inf"), 10, 99, -math.inf]).reshape((2,3))

print(f"x:\n {x}\n")

print(f"np.isinf(x):\n{np.isinf(x)}\n")

print(f"np.isneginf(x):\n{np.isneginf(x)}\n")

print(f"np.isposinf(x):\n{np.isposinf(x)}\n")

Output:

checkinf infinity in numpy arrays

The math module also has an isinf method, though it doesn’t have methods to check positive or negative infinity like np.isposinf and np.isneginf.

Conversely, NumPy also has a method called np.isfinite to check if the value is finite or not.

 

Maximum value for infinity

We have discussed that infinity is a ‘large, undefined number’ that is larger than any finite number.
But there are limitations in a computer on the maximum value a variable can store. We cannot declare any large value, and compare it with infinity.

In Python, there is a value between 1e+308 and 1e+309 that is the maximum value that a float variable can store. The exact value can be found using the attribute sys.float_info.
This displays the various properties of the floating-point datatype on that computer, including the maximum value a float variable can store in Python.
Any value greater than this value is interpreted as infinity.
Similarly, on the negative end, any value below a certain minimum value is interpreted as negative infinity.

print(f"value of 1e+308 is {1e+308}")

print(f"value of 1e+309 is {1e+309}")

import sys

print(f"\nfloat info: {sys.float_info}\n")

print(f"value of 1.7976931348623157e+308 = {1.7976931348623157e+308}")

print(f"value of 1.79769313486231585e+308 = {1.79769313486231585e+308}")

Output:

max value of float in Python

While we are at it, let us also discuss the behavior of the exponentiation (power) operator on infinity.
If we try to find any power(except 0) of infinity, or if we calculate the value of any number(except 1) raised to the power infinity, the result will be infinity.
However, if we perform an exponentiation operation using two finite numbers, and if the result exceeds the maximum allowed value, instead of returning infinity as the result, we get an ‘OverflowError’ with the message ‘Numerical result out of range’.

inf = np.inf

print(f"10^inf = {10**inf}")

print(f"inf^2 = {inf**2}\n")

print(f"inf^0 = {inf**0}")

print(f"inf^0.001 = {inf**0.001}\n")

print(f"1^inf = {1**inf}")

print(f"1.001^inf = {1.001**inf}\n")

print(f"10.0^308 = {10.0**308}")

print(f"10.0^309 = {10.0**309}")

Output:

overflow error with power operator on infinity

 

Comparing Infinity

In this section, we will discuss the various comparison operations in Python involving infinity.

Any number is smaller than +inf. Any number is greater than -inf.
inf is neither smaller nor greater than inf>. It is equal to inf, and not equal to -inf.

inf = float("Inf")

print(f"1000 < inf is {1000 < inf}")

print(f"1000 > inf is {1000 > inf}")

print(f"1000 > -inf is {1000 > -inf}")

print(f"-1000 > -inf is {-1000 > -inf}")

print(f"inf > inf is {inf > inf}")

print(f"inf < inf is {inf < inf}")

print(f"inf >= inf is {inf >= inf}")

print(f"inf == inf is {inf == inf}")

print(f"inf == -inf is {inf == -inf}")

print(f"1e+309 < inf is {1e+309 < inf}")

print(f"1e+309 == inf is {1e+309 == inf}")

Output:

comparison operations with infinity

 

Pass infinity as a command-line argument

When we run a python file from the command line, we can additionally pass any number of arguments we want.
These arguments can be accessed using sys.argv.
sys.argv contains a list of command-line arguments passed to the Python program. The first element in the list is the Python filename, and the remaining elements are the additional values passed (separated by a space) following the filename.

All the values in this list are stored as Python strings.

#cmd_args.py
import sys

print(f"arguments received from command line are: {sys.argv}\n")

datatypes = [type(x) for x in sys.argv]

print(f"type of each command line argument: {datatypes}")

Output:

passing command-line arguments in python

Since all the command-line arguments are received as strings by default, if we want the arguments to be of a certain datatype (eg. float, int, etc.), we need to convert the string arguments into our desired datatype.
In this way, if the user needs to pass ‘infinity’ as one of the arguments, we can convert the same using the float method, and store it in a variable.

Let us take an example where we expect 3 numeric command-line arguments, the first of which is an integer and the remaining ones are float.

#cmd_arg_inf.py
import sys

arguments = sys.argv[1:]

x1 = int(arguments[0])

x2 = float(arguments[1])

max_val = float(arguments[2])

print(f"arguments received: x1={x1}, x2={x2}, max_val={max_val}")

Output:

passing infinity as cmd argument

 

Conclusion

In this tutorial, we understood what infinity is, how it is represented in memory using IEEE standard, and how to represent it and work with it in Python.

We began by defining infinity from mathematical and computing perspectives.
Then, we then discussed various ways of declaring infinity (and their equivalence) in Python.
We reasoned the need for defining infinity using float datatype by discussing the IEEE 754 standard for floating-point numbers.

We looked at various arithmetic operations that we can perform on infinity. While doing this, we discovered another special value called NaN which is also stored as a float value in Python.

We looked at NumPy’s way of declaring infinity and worked with various methods in NumPy to check whether a value (or several values in a NumPy array) are infinity, -infinity, +infinity, etc.

We discussed the maximum value for a float variable that we can store in Python, beyond which everything is considered as infinity.
Then, we discussed the behavior of various comparison operators on infinity.

Finally, we learned how we can pass infinity as a command-line argument in Python.

The post A Foolproof Guide to Infinity In Python appeared first on Like Geeks.


Viewing all articles
Browse latest Browse all 104

Trending Articles