Why 0.123456789 == 12.3456789 / 100 is True? [closed] - python

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last year.
Improve this question
I know the floating point issues and I've read some documentations and have some understanding on Decimal type.
For example: .1 + .1 + .1 != .3 .
But why:
>>> 0.123456789 == 12.3456789 / 100
True
is True ? I expected False.
Because adding is inaccurate so I think division should also be inaccurate?

Not really an answer, but too long for the comments:
To explore this phenomenon, I wrote a simple program:
import random
def f(a,b,n):
x = random.uniform(a,b)
y = n*x
return x,y,x == y/n
Then for example
trials = [f(0,100,100) for _ in range(10000)]
print(len([x for x,y,t in trials if t])/10000)
prints values like 0.8634
I have tried a number of values for a,b,n, with == holding typically in the range 80% to 90%. A strange observation which confuses me:
f(0,100,100000000)
is much more likely to give rise to a counterexample than either
f(0,100,10000000)
or
f(0,100,10000000000)
I would have thought that for a,b fixed, the probability of x==y is monotonic in n, but it apparently isn't.

Related

How does the choice of units impact numerical precision? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 months ago.
Improve this question
I write science-related codes with Python and I was wondering how the choice of units may affect my results.
For example, if I enter a distance as 1e-9 meters or 1 nm or 10 Angstroms, I would obtain the exact same result on paper. However, I know that the representation of these quantities is different on a computer. Therefore, I would like to know how important it is to choose the relevant set of units in scientific computing to maximize numerical precision.
How does the choice of units impact numerical precision?
I suggest you get as first step clarity what 'numerical precision' actually means with the side-effect of accepting the statement It doesn't affect it at all provided by Tim Roberts in the comments as short, clear and simple answer.
Usually you choose numerical precision yourself in your code by choice of the data types storing values and the way you perform calculations on these values.
The choice of units is just a choice of units and choice of data types for numerical representation of values in this units is another story.
In other words you have to know first what you actually want to do and how to achieve the results you expect.
Let's for example consider following code:
x = 1.0
dx = 0.000_000_000_000_000_1
steps = 1_000_000
for i in range(steps):
x += dx
print(x)
x = 1.0
x += sum([dx]*steps)
print(x)
x = 1.0
x += dx*steps
print(x)
printing:
1.0
1.0000000001
1.0000000001
as evidence that the choice of the way of performing calculations is the main issue when you experience surprising results and not the numerical precision or choice of units as such.

Sum of digit of a number using recursion in python [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 months ago.
Improve this question
Here in this program, I tried to understand but couldn't get completely.
How is this recursive function doing the sum and returning total sum of this? Please explain me in detail?
# Recursive Python3 program to
# find sum of digits of a number
# Function to check sum of
# digit using recursion
def sum_of_digit( n ):
if n < 10:
return n
return (n % 10 + sum_of_digit(n // 10)) # how this is working ?
num = 12345
result = sum_of_digit(num)
print("Sum of digits in",num,"is", result)
The best way to understand a recursive function is to dry run it.
First you need to understand what n % 10 mean is. this means the remainder of a n when divided by 10.
In this case when we divide 12345 by 10 , we get 5 as remainder.
so n % 10 part of code becomes 5.
Now, the second part is n//10 which gives you 1234 that are remaining digits.
Applying the same function again will give you 4 + sum_of_digit(123) and so on.
Even if this do not clear your confusion try, running this code on paper with some small number.

Smart rounding an array in Python [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 12 months ago.
Improve this question
I'd like to make a function that rounds integers or floats homogeneously and smart. For example, if I have an array like:
[0.672, 0.678, 0.672]
my output would be:
[0.67, 0.68, 0.67]
but also if I have this kind of input:
[17836.982, 160293.673, 103974.287]
my output would be:
[17836, 160293, 103974]
But at the same time, if my array only has close together values such as:
[17836.987, 17836.976, 17836.953]
The output would be:
[17836.99, 17836.98, 17836.95]
An automated way could be to compute all absolute differences, getting the min and finding out the number of decimal places to keep to maintain a representative difference.
This doesn't give the exact output you want but follows the general logic.
Here using numpy to help on the computation, the algorithm is O(n**2):
def auto_round(l, round_int_part=False):
import numpy as np
a = np.array(l)
b = abs(a-a[:,None])
np.fill_diagonal(b, float('inf'))
n = int(np.ceil(-np.log10(b.min())))
# print(f'rounding to {n} decimals') # uncomment to get info
if n<0:
if not round_int_part:
return a.astype(int).tolist()
return np.round(a, decimals=n).astype(int).tolist()
return np.round(a, decimals=n).tolist()
auto_round([17836.987, 17836.976, 17836.953])
# [17836.99, 17836.98, 17836.95]
auto_round([0.6726, 0.6785, 0.6723])
# [0.6726, 0.6785, 0.6723]
auto_round([17836.982, 160293.673, 103974.287])
# [ 17836, 160293, 103974]
auto_round([17836.982, 160293.673, 103974.287], round_int_part=True)
# [20000, 160000, 100000]

More Pythonic way to loop through a range [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
A friend asked me to make her coding more "pythonic" but I'm pretty new at it myself. This is what I came up with, and I'm a little concerned that it won't hit all of the numbers (6, 7, 8, 9, 10 and 11). I also KNOW that there is a better way, but I just don't know what it is. Can you help?
prob = 0
for r in range(6,11):
prob += binom.pmf(k=r, n=11, p=0.2)
print(‘The probability is {}’,format(prob))
I think that your code is perfectly pythonic, for what that's worth
You could make it a little more compact and more performant with a list comprehension, the sum() function, and an f-string. Also, I took into account that you wanted 11 inclusive, so your range should be from 6 to 12.
probs = [binom.pmf(k=r, n=11, p=0.2) for r in range(6, 12)]
print(f'The probability is {sum(probs)}')
Use list comprenhension:
def binom(n,r,p):
# dummy function
return n+r+p
prob = sum([binom(r,12, 0.2) for r in range(6,11)])
print(f"The probability is {prob}")
Edit:
To make 11 inclusive, increase your range to 12
Edit 2:
As suggested by OneCricketeer, if only need to compute the sum, you can remove the square brackets, like so:
prob = sum(binom(r,12, 0.2) for r in range(6,11))

If elif else construct and full DRY conform [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
first of all I am sorry for the bad title but I didn't know what would be appropriate. I am looking for a better syntax for the following block so that I am not repeating myself.
self.rulerMajorTickLabel and self.rulerMinorTickLabel can either be True or False
self.rulerMajorTickWidth and self.rulerMinorTickWidth can only be a positive float
if self.rulerMajorTickLabel and self.rulerMinorTickLabel:
if self.rulerMajorTickWidth > self.rulerMinorTickWidth:
halfTickHeight = self.rulerMajorTickWidth / 2
else:
halfTickHeight = self.rulerMinorTickWidth / 2
elif self.rulerMajorTickLabel:
halfTickHeight = self.rulerMajorTickWidth / 2
elif self.rulerMinorTickLabel:
halfTickHeight = self.rulerMinorTickWidth / 2
else:
halfTickHeight = 0
Thanks you very!
Assuming a few things here to make it work elegantly, so you might want to make sure of that somewhere else in the code. My assumptions:
self.rulerMajorTickWidth and self.rulerMinorTickWidth are either a positive number, or equal to zero
They are both defined as attributes and looking for them will not throw an error
You want just the larger of the two to divide by 2
Assuming all that, you can simply do:
halfTickHeight = max(self.rulerMajorTickWidth, self.rulerMinorTickWidth) / 2
If their "false" value however is either None or undefined, it's more complicated. That's why I suggest making sure in other places in the code that it's either 0 or an integer/float. If they are actually the boolean False you can float() them to equal 0
Edit: Because I just noticed the labels are different than the width parts, you can still preform all of your checks more easily by doing this:
tmpMajor = self.rulerMajorTickWidth if self.rulerMajorTickLabel else 0
tmpMinor = self.rulerMinorTickWidth if self.rulerMinorTickLabel else 0
halfTickHeight = max(tmpMajor, tmpMinor) / 2
Which is equivalent to all your if...elif...else clauses from before

Categories