getting wrong number when too many decimals [duplicate] - python

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 10 months ago.
In this program, I am asking the user to input two datetime, and I convert the differences between the two date times into several floats. difference_days is one of the float of total difference in days.
so basically, I am writing this in for loop
part of my code is below:
if difference_days.is_integer():
print(f'The difference is {int(difference_days)} days.')
else:
hours = (difference_days - int(difference_days))*24.0
print(int(difference_days))
print(difference_days)
print(difference_days - int(difference_days))
print(hours)
if difference_hours.is_integer():
print(f'The difference is {int(difference_days)} days and {int(hours)} hours.')
else:
... # other codes that handle minutes, seconds, microseconds
I did not post all the codes, because I think there's something wrong with the calculation in python.
so those print statements between hours and the second if statement is just for test, and below is the output:
91
91.95833333333333
0.9583333333333286
22.999999999999886
I was confused why the third one starts to have more decimal places in the end while the second doesn't. How should I fix that? I would like it to only display the 12 decimals.

You can just use the format() function, and convert it to a floating point, like this:
float(format(difference_days,".12f"))
This will return difference_days as a floating point with 12 decimals

Well I guess I just found the solution, so I did the following, but any better ideas?
from decimal import *
getcontext().prec = 12
hours = (Decimal(difference_days) - int(difference_days))*24

Floating points can't be perfectly represented in binary, so you will always have the weird error at the end.
Why are floating point numbers inaccurate?
But you can print the 12 digits of the decimal with:
>>> x = 0.9583333333333286
>>> f'{x:.12f}'
'0.958333333333'
>>> float(f'{x:.12f}')
0.958333333333

Related

Very big number with floating point in Python [duplicate]

This question already has answers here:
How to get largest possible precision? (Python - Decimal)
(4 answers)
Closed 5 months ago.
I have done some research throughout SO and I believe this is not a duplicate of How to get largest possible precision? (Python - Decimal) or Arithmetic precision problems with large numbers or How to store a big floating point number in python variable?
Let's say that I have this number: 11400361308443875328.123123123123
What data type can I use to store this in Python? I have tried float, decimal and the result it gives me:
x = Decimal('11400361308443875328.123123123123123') + Decimal('11400361308443875328.123123123123123')
print("{:12f}".format(x))
# 22800722616887750656.24624625
y = float(11400361308443875328.123123123123) + float(11400361308443875328.123123123123)
print("{:12f}".format(y))
# 22800722616887750656.000000
z = Decimal('0.123123123123123') + Decimal('0.123123123123123')
print("{:12f}".format(z))
# 0.246246246246246
I need the degree of precision that z has. How should I store this big number with floating precision so that I can do some mathematical operations on it? Is there some trick on how I can do this?
For the question on why I need this high degree of precision: this is a question from a coding challenge (not the actual question), and the submission is graded with a leeway of +- 10^-6 precision
If decimal's default precision is not enough, you can change it by modifying value of getcontext().prec - https://docs.python.org/3/library/decimal.html#module-decimal
from decimal import Decimal, getcontext
getcontext().prec = 50
x = Decimal('11400361308443875328.123123123123123') + Decimal('11400361308443875328.123123123123123123')
print(x) # 22800722616887750656.246246246246246123

Python round - Two deciding decimals [duplicate]

This question already has answers here:
How to round a number to significant figures in Python
(26 answers)
Closed 1 year ago.
I want to round numbers so that two numbers are used after the last zero, or decimal if the number is greater than 1. I've looked up the documentation for round, but can't seem to find this feature.
If I use round, it always round to n decimals places regardless.
This is the output I'm looking for:
42.0068 --> 42.01
0.00251 --> 0.0025
420.246 --> 420.25
0.192 -> 0.19
0.00000000128 --> 0.0000000013
The kind of rounding you're asking for isn't a common operation.
In terms of common operations you have two cases (ignoring sign since all your examples are positive):
If the value is less than 1, round to significant figures (eg per the link in #quamrana's comment on the question).
Else (ie the value is at least 1), round to decimal places in the usual way.
Your final code would reasonably be a function with a simple if-else:
def round_special(value):
if value < 1:
return round_to_sf(value, 2)
else:
return round_to_dp(value, 2)
You could try with string manipulation. It's not that elegant, but seems to work. It's up to you to complete this code to handle exceptions..
if number>1:
result = round(number,2)
else:
str_number = str(number)
i = str_number.rfind('0')
result = float(str_number[:i+3])

Need help on newbie coding (python) [duplicate]

This question already has answers here:
How to print float to n decimal places including trailing 0s?
(5 answers)
Closed 2 years ago.
It's my first week trying to learn how to code.
Rods is input from user so it can be whatever
miles = round(Rods * 0.003125, 20)
print("Distance in Miles = ", miles)
I need this line of code to print 20 decimals. I thought by adding comma 20 it would do so. I then tried looking re-writing it to format{miles: "20.f"}. (Don't remember exactly how the code went)
Any guidance would be appreciated.
Try this snippet:
miles = Rods * 0.003125
print("Distance in Miles = {:.20f}".format(miles))
This code does the calculation first and formats the answer such that it is displayed in 20 decimal places. For displaying only 10 decimal places change to .10f, for 2 decimal places change to .2f and so on.
When calling round() method on floats, the unnecessary leading decimal zeros are not counted, since the number is the same.
You can convert the number to string, use .split(".") on it to separate the decimal and whole number
example: "3.85".split(".") will return a list whose elements are ["3", "85"] digits = str(num).split(".")
Lets take the second element, decimals decimals = digits[1]
Then you take the length of second element that is decimals and subtract it from 20. This will be the amount of zeros to add. newDecimals = decimals + (20 - len(decimals)) * "0"
Now, use the list from before to form a new number
final = digits[0] + "." + newDecimals
Keep in mind that converting it back to a float will remove those zeros.
Try following source code :
miles = Rods * 0.003125
miles_formatted_float = "{:.20f}".format(miles)
print("Distance in Miles = "+miles_formatted_float)

Finding the last digit of decimal number

We all know that if we want to find the last number of 1182973981273983 which is 3 we simply do this:
>>> print(1182973981273983 % 10)
3
But if I want to get the last number of 2387123.23 I was thinking of doing this:
>>> 2387123.23 % 10 ** (-1 * 2)
0.009999999931681564
But it doesn't work. What is the mathematical way of getting the last number a decimal number.
p.s. String solutions are invalid. We are programmers we need to know how math works.
As people have already pointed out in the comments, this is not possible for floating point numbers; the concept of 'last decimal' simply doesn't apply. See links in comments for more details.
On the other hand, this would work if you were using fixed point arithmetic (i.e. the Decimal type). Then a solution might look like this:
>>> import decimal
>>> d = decimal.Decimal('3.14')
>>> d.as_tuple().digits[-1]
4

How does print "%.1f" % number really works in Python? [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Is floating point arbitrary precision available?
(5 answers)
Closed 7 years ago.
I don't know if this is an obvious bug, but while running a Python script for varying the parameters of a simulation, I realized the results with delta = 0.29 and delta = 0.58 were missing. On investigation, I noticed that the following Python code:
for i_delta in range(0, 101, 1):
delta = float(i_delta) / 100
(...)
filename = 'foo' + str(int(delta * 100)) + '.dat'
generated identical files for delta = 0.28 and 0.29, same with .57 and .58, the reason being that python returns float(29)/100 as 0.28999999999999998. But that isn't a systematic error, not in the sense it happens to every integer. So I created the following Python script:
import sys
n = int(sys.argv[1])
for i in range(0, n + 1):
a = int(100 * (float(i) / 100))
if i != a: print i, a
And I can't see any pattern in the numbers for which this rounding error happens. Why does this happen with those particular numbers?
Any number that can't be built from exact powers of two can't be represented exactly as a floating point number; it needs to be approximated. Sometimes the closest approximation will be less than the actual number.
Read What Every Computer Scientist Should Know About Floating-Point Arithmetic.
Its very well known due to the nature of floating point numbers.
If you want to do decimal arithmetic not floating point arithmatic there are libraries to do this.
E.g.,
>>> from decimal import Decimal
>>> Decimal(29)/Decimal(100)
Decimal('0.29')
>>> Decimal('0.29')*100
Decimal('29')
>>> int(Decimal('29'))
29
In general decimal is probably going overboard and still will have rounding errors in rare cases when the number does not have a finite decimal representation (for example any fraction where the denominator is not 1 or divisible by 2 or 5 - the factors of the decimal base (10)). For example:
>>> s = Decimal(7)
>>> Decimal(1)/s/s/s/s/s/s/s*s*s*s*s*s*s*s
Decimal('0.9999999999999999999999999996')
>>> int(Decimal('0.9999999999999999999999999996'))
0
So its best to always just round before casting floating points to ints, unless you want a floor function.
>>> int(1.9999)
1
>>> int(round(1.999))
2
Another alternative is to use the Fraction class from the fractions library which doesn't approximate. (It justs keeps adding/subtracting and multiplying the integer numerators and denominators as necessary).

Categories