Why can the difference of different floating numbers be 0 in python? [duplicate]

2024/10/9 18:20:52

Why is the result of below code 0 in python3?

a = "4.15129406851375e+17"
a = float(a)
b = "415129406851375001"
b = float(b)
a-b
Answer

This happens because both 415129406851375001 and 4.15129406851375e+17 are greater than the integer representational limits of a C double (which is what a Python float is implemented in terms of).

Typically, C doubles are IEEE 754 64 bit binary floating point values, which means they have 53 bits of integer precision (the last consecutive integer values float can represent are 2 ** 53 - 1 followed by 2 ** 53; it can't represent 2 ** 53 + 1). Problem is, 415129406851375001 requires 59 bits of integer precision to store ((415129406851375001).bit_length() will provide this information). When a value is too large for the significand (the integer component) alone, the exponent component of the floating point value is used to scale a smaller integer value by powers of 2 to be roughly in the ballpark of the original value, but this means that the representable integers start to skip, first by 2 (as you require >53 bits), then by 4 (for >54 bits), then 8 (>55 bits), then 16 (>56 bits), etc., skipping twice as far between representable values for each bit of magnitude you have that can't be represented in 53 bits.

In your case, both numbers, converted to float, have an integer value of 415129406851374976 (print(int(a), int(b)) will show you the true integer value; they're too large to have any fractional component), having lost precision in the low digits.

If you need arbitrarily precise base-10 floating point math, replace your use of float with decimal.Decimal (conveniently, your values are already strings, so you don't risk loss of precision between how you type a float and the actual value stored); the default precision will handle these values, and you can increase it if you need larger values. If you do that, you get the behavior you expected:

from decimal import Decimal as Dec  # Import class with shorter namea = "4.15129406851375e+17"
a = Dec(a)  # Convert to Decimal instead of float
b = "415129406851375001"
b = Dec(b)  # Ditto
print(a-b)

which outputs -1. If you echoed it in an interactive interpreter instead of using print, you'd see Decimal('-1'), which is the repr form of Decimals, but it's numerically -1, and if converted to int, or stringified via any method that doesn't use the repr, e.g. print, it displays as just -1.

Try it online!

https://en.xdnf.cn/q/118550.html

Related Q&A

twinx and sns.barplot seaborn are overlapping bars

I would like to use sns.seaborn to display the np.sum and the np.mean on 2 different axes (with ax2 = ax1.twinx() I assume). The probem I have is that the graphs are overlapped and not readable.Am I ap…

Cant get tensorflow on Anaconda [duplicate]

This question already has an answer here:TensorFlow Importing error ( Using Anaconda)(1 answer)Closed 2 years ago.I need tensorflow to run a guided project I did on Coursera, but I am not able to insta…

Extract number between text and | with RegEx Python

I want to extract the information between CVE and |, but only the first time that CVE appear in the txt. I have now the follow code:import re f = open (/Users/anna/PycharmProjects/extractData/DiarioOfi…

How to reset a loop that iterates over a set?

How can I reset a loop that iterates over a set? A common answer for iterating over a list is to reset the index you are using to access the list, however sets do not support indices. The point is to …

Can i set a threading timer with clock time to sync with cron job in python

I have a cron job that runs at 12, 12:30,1, 1:30. So every half hour intervals on the clock. I want to run a thread in my python code whenever the cron job runs.I have seen examples where to run a tim…

How do I make a simple countdown time in tkinter?

I am making a simple countdown timer in minutes. I cant seem to display the countdown in text label. Can someone help me?import tkinter as tk import timedef countdown(t):while t:mins, secs = divmod(t,…

Embed one pdf into another pdf using PyMuPDF

In need of help from learned people on this forum. I just want to embed one pdf file to another pdf file. So that when I go to the attachment section of the second file I can get to see and open the fi…

How to fix - TypeError: write() argument must be str, not None

Here is my code - sentence = input("Enter a sentence without punctuation") sentence = sentence.lower() words = sentence.split() pos = [words.index(s)+1 for s in words] hi = print("This s…

Is there a way to get source of a python file while executing within the python file?

Assuming you have a python file like so#python #comment x = raw_input() exec(x)How could you get the source of the entire file, including the comments with exec?

How can I stop find_next_sibling() once I reach a certain tag?

I am scraping athletic.net, a website that stores track and field times. So far I have printed event titles and times, but my output contains all times from that season rather than only times for that …