Learn the Basics of Float in Python - Part 1
Master Python Float Fundamentals: A Beginner's Guide
In Python, a float
is a built-in data type used to represent floating-point numbers, which are real numbers with a decimal point or numbers in scientific notation. Floats are used for performing arithmetic operations that involve non-integer values. Floats in Python are implemented using the IEEE 754 standard, which specifies how floating-point numbers are stored and manipulated in binary. This means that floating-point numbers have a finite precision, and certain operations can result in rounding errors.
Internal Representation of Float
The float
data type uses a fixed number of bytes to store data, typically 8 bytes, which corresponds to 64 bits on most systems. This is the standard implementation for representing double-precision floating-point numbers (i.e., numbers with 64-bit precision) according to the IEEE 754 standard.
However, it's important to note that in addition to the actual data stored in a float
, Python objects have some overhead associated with them. This overhead includes information about the type of the object, reference count, and other metadata required by the Python interpreter for memory management and garbage collection. This overhead can vary depending on the implementation of Python (e.g., CPython, Jython, IronPython) and the underlying memory management system.
So, while the data in a float
itself occupies 8 bytes (64 bits), the actual memory usage for a Python float
object will be slightly larger due to this overhead.
Here's a simple example to illustrate this concept using the sys.getsizeof()
function to get the size of a Python object:
>>> import sys
>>> x = 3.14 # a float
>>> sys.getsizeof(x) # in bytes
24
Here is how 64 bits are used up
sign | 1 bit | 0 for positive(+) |
exponent | 11 bits | range[-1022 ,1023] |
significant digits | 52 bits | 15-17 significant digit(base - 10) |
We can represent floating-point numbers as a combination of a base-10 integer and a fractional part. This representation is commonly known as "fixed-point" representation. In this approach, you split a floating-point number into two parts: an integer part and a fractional part. The integer part represents the whole number portion, and the fractional part represents the decimal or fractional portion.
In the above, we can see the example of 2 significant digits represented as integers and a fraction part. In general, we can use the below formula to represent a floating-point number as an integer and factor part.
In general, we can represent the float as integers and a fraction part using below mathematic formula
some numbers cannot be represented using a finite number of terms. numbers such as 3.14 and 1.414 we have even some rational number in that case like 1/3
Equality Testing in float
In the aforementioned discussion, we encountered several instances where certain floating-point numbers cannot be accurately represented using a finite number of terms. This inherent limitation in the representation of floating-point numbers can potentially introduce unexpected issues or inaccuracies in our code. It is crucial to note that these inaccuracies are not a result of any bugs within the Python programming language itself, but rather stem from the nature of floating-point arithmetic.
To elaborate, we can generally represent a floating-point number as a combination of an integer part and a fractional part, as demonstrated by the following mathematical formula:
floating-point number = integer part + fractional part
However, there are specific numbers, such as 3.14 and 1.414, which cannot be precisely represented using a finite number of terms. Additionally, there are rational numbers like 1/3 that also fall into this category. This imprecision can lead to complications when performing equality testing with floating-point numbers, as the results may not always align with our expectations due to the inherent inaccuracies in their representation.
>>> x = 0.1 + 0.1 + 0.1
>>> format(x,'.25f')
'0.3000000000000000444089210'
>>> y = 0.3
>>> format(y,'.25f')
'0.2999999999999999888977698'
>>> x == y
False
The text demonstrates that due to floating-point inaccuracies, the variables x and y, which we expect to be equal, are not considered equal when compared directly.
using the round function might seem like a solution to the floating-point inaccuracies issue, but it doesn't guarantee to resolve the problem in all cases.
>>> round(0.1,1) + round(0.1,1) + round(0.1,1)
0.30000000000000004
>>> round(0.3,1)
0.3
>>> round(0.1,1) + round(0.1,1) + round(0.1,1) == round(0.3,1)
False
It is no more possible to exactly represent round(0.1,1)
than 0.1 itself. But it can be used to round the entirety of both sides of the quality comparison.
>>> round(0.1+0.1+0.1,5)
0.3
>>> round(0.3,5)
0.3
>>> round(0.1+0.1+0.1,5) == round(0.3,5)
True
This article discusses the float data type in Python, its internal representation, and the challenges of equality testing due to floating-point inaccuracies. Floats are used for arithmetic operations involving non-integer values and are implemented using the IEEE 754 standard. The memory usage of a Python float object includes both the data and additional overhead. The article also explains the concept of fixed-point representation and demonstrates the issues with equality testing in floating-point numbers caused by their inherent imprecision. It highlights that using the round function can help mitigate these issues in some cases.