Use python to calculate a special limit - python

I want to calculate this expression:
(1 + 1 / math.inf) ** math.inf,
which should evaluates to e. However Python returns 1. Why is that?
=====UPDATE========
What I want to do here is to derive the effective annual rate from user's input, APR (annual percentage rate).
def get_EAR(APR, conversion_times_per_year = 1):
return (1 + APR / conversion_times) ** conversion_times - 1
I would want this expression to also apply to continuous compounding. Yes I understand I can write if statements to differentiate continuous compounding from normal cases (and then I can use the constant e directly), but I would better prefer an integrated way.

The calculation of limits is not implemented in python by default, for this you could use sympy
from sympy import *
x= symbols('x')
r = limit((1+1/x)**x, x, oo)
print(r)
Output:
E

Because you are esssentially performing two separate limits:
lim x->infty ((lim y->infty (1 + 1/y))^x)
which Python correctly evaluates as 1.
Here is a poor-man's-implementation of the proper limit:
def euler(x):
return (1+1/x)**x
for i in range(10):
print(euler(10**i))
2.0
2.5937424601000023
2.7048138294215285
2.7169239322355936
2.7181459268249255
2.7182682371922975
2.7182804690957534
2.7182816941320818
2.7182817983473577
2.7182820520115603

You could use the mpmath (http://mpmath.org/) package here:
>>> import mpmath as mp
>>> f = lambda x: (1.0 + 1.0/x)**x
>>> mp.limit(f, mp.inf)
mpf('2.7182818284590451')

I think there is no limit calculation here since there is no variable here that for which the whole statement can be calculated at different values of the variable.
Python simply does the calculation the simplest way possible. Pythons compiler simply turns the 1/math.inf to 0 and then evaluates 1 to the power of math.inf as 1.

Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)] on win32
import sys
import math
E = sys.float_info.epsilon
e = (1 + E) ** (1 / E)
print(e, math.e, e == math.e)
OUTPUT:
2.718281828459045 2.718281828459045 True

Related

Is there a way to know whether something was rounded up or down in python? [duplicate]

This question already has answers here:
Round to 5 (or other number) in Python
(21 answers)
Closed 2 years ago.
I basically want to know whether the result of my equation (which is a simple one like this x / y) was rounded up or down.
The reason is that I have two simple statements after the rounding line like this:
if h % 2 != 0: h = h + 1
if h % 4 != 0: h = h + 2
and based on the direction of the rounding I would choose the + or - operator, so if the result was rounded up and h % 2 != 0 then it would be h = h + 1 and if it was rounded down then h = h - 1.
Does round() give that kind of information?
Also, is my math correct? (I want the result to be dividable by 4)
Try this to round to 4 directly :
import math
h = 53.75
rounded = math.round(h / 4) * 4
if (rounded > h):
print("Rounded up by " + str(rounded - h))
else:
print("Rounded down by " + str(h - rounded))
Using round() if the number after the given decimal is:
>=5 that + 1 will be added to the final value.
<5 that the final value will return as is to the mentioned decimals.
But you can use ceil or floor from the math package where it always rounds up or down, respectively.
import math
>>> math.ceil(5.2)
6
>>> math.floor(5.9)
5
Let's say you want to know whether 3.9 and 4.4 were rounded. You can do something like this:
def is_rounded_down(val, ndigits=None):
return round(val, ndigits) < val
Then you can simply call the function to find out
>>> is_rounded_down(3.9)
False
>>> is_rounded_down(4.4)
True
By default round() doesn't give that information, so you need to check yourself.
For Python 2.X integer division returns an integer and always rounds down.
add#LM1756:~$ python
Python 2.7.13 (default, Sep 26 2018, 18:42:22)
>>> print 8/3
2
>>> print type(5/2)
<type 'int'>
For Python 3.X integer division returns a float, and so there is no rounding.
add#LM1756:~$ python3
Python 3.5.3 (default, Sep 27 2018, 17:25:39)
>>> print(8/3)
2.6666666666666665
>>> type(8/3)
<class 'float'>
>>>

Sympy: There remains some terms which shuold be obviously vanished

I want to calculate derivative of a function using following code.
import sympy
pi = sympy.symbols("pi")
class H(sympy.Function):
nargs = 1
def fdiff(self, argindex=1):
x = self.args[0]
return - sympy.functions.exp(-sympy.Pow(x, 2) / 2) / sympy.sqrt(2 * pi)
def G(a):
return (
(a + 1) * H(1 / sympy.sqrt(a))
- sympy.sqrt(a / (2 * pi)) * sympy.functions.exp(-1 / (2 * a))
)
x = sympy.symbols("x")
sympy.simplify(sympy.diff(G(x), x))
It is expected to be G'(x) = H(1 / sqrt(x)), but I got
Out[1]: H(1/sqrt(x)) - sqrt(2)*sqrt(x/pi)*exp(-1/(2*x))/(4*x) - sqrt(2)*sqrt(x/pi)*exp(-1/(2*x))/(4*x**2) + sqrt(2)*exp(-1/(2*x))/(4*sqrt(pi)*sqrt(x)) + sqrt(2)*exp(-1/(2*x))/(4*sqrt(pi)*x**(3/2))
The remaining terms should obviously be 0 when seen by human eye.
Then I tried to change two pis in the definition of H and G to sympy.pi, which returns H(1 / sqrt(x)) as I expected.
Why my first code returns some extra terms?
SymPy has built in rules which allow certain transformations to happen (automatically, sometimes) or to be prohibited (by default). When you defined pi as a Symbol, you created a generic symbol with the only assumption being that it is commutative. But the number pi is that and it is positive. That assumption allows something like sqrt(x/y) to automatically rewrite as sqrt(y)*sqrt(x)/y if y is positive:
>>> sqrt(x/y)
sqrt(x/y)
>>> sqrt(x/3)
sqrt(3)*sqrt(x)/3
If you take your last expression and substitution a positive value for the symbol pi you will get that rewrite and then the cancelling terms will cancel.
>>> print(sympy.simplify(sympy.diff(G(x), x))).subs(pi, 3)
H(1/sqrt(x))
As Johan points out, it is better in this case to just use SymPy's S.Pi:
>>> S.Pi.n(3)
3.14

Python: looking for a faster, less accurate sqrt() function

I'm looking for a cheaper, less accurate square root function for a high volume of pythagorus calculations that do not need highly accurate results. Inputs are positive integers, and I can upper-bound the input if necessary. Output to 1dp with accuracy +- 0.1 if good, but I could even get away with output to nearest integer +- 1. Is there anything built into python that can help with this? Something like math.sqrt() that does less approximations perhaps?
As I said in my comment, I do not think you will do much better in speed over math.sqrt in native python given it's linkage to C's sqrt function. However, your question indicates that you need to perform a lot of "Pythagoras calculations". I am assuming you mean you have a lot of triangles with sides a and b and you want to find the c value for all of them. If so, the following will be quick enough for you. This leverages vectorization with numpy:
import numpy as np
all_as = ... # python list of all of your a values
all_bs = ... # python list of all of your b values
cs = np.sqrt(np.array(all_as)**2 + np.array(all_bs)**2).tolist()
if your use-case is different, then please update your question with the kind of data you have and what operation you want.
However, if you really want a python implementation of fast square rooting, you can use Newton'ss method` to do this:
def fast_sqrt(y, tolerance=0.05)
prev = -1.0
x = 1.0
while abs(x - prev) > tolerance: # within range
prev = x
x = x - (x * x - y) / (2 * x)
return x
However, even with a very high tolerance (0.5 is absurd), you will most likely not beat math.sqrt. Although, I have no benchmarks to back this up :) - but I can make them for you (or you can do it too!)
#modesitt was faster than me :)
Newton's method is the way to go, my contribution is an implementation of Newton's method that is a bit faster than the one modesitt suggested (take sqrt(65) for example, the following method will return after 4 iterations vs fast_sqrt which will return after 6 iterations).
def sqrt(x):
delta = 0.1
runner = x / 2
while abs(runner - (x / runner)) > delta:
runner = ((x / runner) + runner) / 2
return runner
That said, math.sqrt will most certainly be faster then any implementation that you'll come with. Let's benchmark the two:
import time
import math
def timeit1():
s = time.time()
for i in range(1, 1000000):
x = sqrt(i)
print("sqrt took %f seconds" % (time.time() - s))
def timeit2():
s = time.time()
for i in range(1, 1000000):
x = math.sqrt(i)
print("math.sqrt took %f seconds" % (time.time() - s))
timeit1()
timeit2()
The output that I got on my machine (Macbook pro):
sqrt took 3.229701 seconds
math.sqrt took 0.074377 seconds

x ** 1/3 in python? [duplicate]

This question already has answers here:
How to find integer nth roots?
(11 answers)
Closed 7 years ago.
Recently I encountered a problem:
I want to calculate various roots of various numbers like this:
x = x ** 1/y+1
None of the methods I know result in a working code.
Method 1:
x = 54
y = 2
x = x ** 1/y+1
print(x)
Printed value is 28.0 instead of 3.7798
Method 2:
x = 54
y = 2
x = x ** 1/(y+1)
print(x)
Printed value is 18.0 istead of 3.7798
Method 3:
x = 216
y = 2
x = x ** (1/(y+1))
print(x)
Printed value is 5.99 instead of 6
Is there a way that would work with y being up to 20?
Edit:
Another suggested method:
def nth_root(val, n):
ret = int(val**(1./n))
return ret + 1 if (ret + 1) ** n == val else ret
y = 1
print(nth_root(19, (y+1)))
prints 4
Since everyone else has already told you why your Method 3 is correct, I'll stick to getting you an accurate answer. You can read more about why you're not getting exactly 6, but basically it's because your computer doesn't represent the 1/3 exactly when doing the calculation and makes the final answer off.
So, the easiest solution is to use sympy:
import sympy
y = 216
x = 2
x = sympy.root(y,x+1)
print(x)
You don't seem to understand (yet) order of operations in a programming language. You need parentheses to make sure you add 1 to y, then take the reciprocal, and then use that as an exponent. The "natural" order is the opposite.
x = x ** (1.0/(y+1))
What you want is this (assuming you are using Python 3):
x = x ** (1/(y+1))
For Python 2, either of the following will work:
from __future__ import division
x = x ** (1/(y+1))
or (also fine on Python 3):
x = x ** (1.0/(y+1))
The issue is you need to apply the parentheses in the correct locations to get the order of operations right.
Method 3 is to do with floating point arithmetic. See: https://docs.python.org/3.5/tutorial/floatingpoint.html
For more info on Python 2 vs. Python 3 division:
Division in Python 2.7. and 3.3
Only your last code works because ** has higher precedence than / (and / has higher precendence than +).
The value is not exactly 6, because floating point numbers are not perfectly accurate. A third can not be represented as a float.
All your values are just as expected. According to the python operator precedence:
x ** 1/y+1 is parsed as ((x ** 1) / y) + 1, and
x ** 1/(y+1) is actually (x ** 1) / (y + 1).
What you probably want is x ** (1. / (y + 1)). Note, that 1. is a floating point number, causing the whole expression to be evaluated as floats. This also means that you will work with finite precision, e.g., getting 5.99999 instead fo 6 is to be expected.

Finding appropriate cut-off values

I try to implement Hampel tanh estimators to normalize highly asymmetric data. In order to do this, I need to perform the following calculation:
Given x - a sorted list of numbers and m - the median of x, I need to find a such that approximately 70% of the values in x fall into the range (m-a; m+a). We know nothing about the distribution of values in x. I write in python using numpy, and the best idea that I had is to write some sort of stochastic iterative search (for example, as was described by Solis and Wets), but I suspect that there is a better approach, either in form of better algorithm or as a ready function. I searched the numpy and scipy documentation, but couldn't find any useful hint.
EDIT
Seth suggested to use scipy.stats.mstats.trimboth, however in my test for a skewed distribution, this suggestion didn't work:
from scipy.stats.mstats import trimboth
import numpy as np
theList = np.log10(1+np.arange(.1, 100))
theMedian = np.median(theList)
trimmedList = trimboth(theList, proportiontocut=0.15)
a = (trimmedList.max() - trimmedList.min()) * 0.5
#check how many elements fall into the range
sel = (theList > (theMedian - a)) * (theList < (theMedian + a))
print np.sum(sel) / float(len(theList))
The output is 0.79 (~80%, instead of 70)
You need to first symmetrize your distribution by folding all values less than the mean over to the right. Then you can use the standard scipy.stats functions on this one-sided distribution:
from scipy.stats import scoreatpercentile
import numpy as np
theList = np.log10(1+np.arange(.1, 100))
theMedian = np.median(theList)
oneSidedList = theList[:] # copy original list
# fold over to the right all values left of the median
oneSidedList[theList < theMedian] = 2*theMedian - theList[theList < theMedian]
# find the 70th centile of the one-sided distribution
a = scoreatpercentile(oneSidedList, 70) - theMedian
#check how many elements fall into the range
sel = (theList > (theMedian - a)) * (theList < (theMedian + a))
print np.sum(sel) / float(len(theList))
This gives the result of 0.7 as required.
Restate the problem slightly. You know the length of the list, and what fraction of the numbers in the list to consider. Given that, you can determine the difference between the first and last indices in the list that give you the desired range. The goal then is to find the indices that will minimize a cost function corresponding to the desired symmetric values about the median.
Let the smaller index be n1 and the larger index by n2; these are not independent. The values from the list at the indices are x[n1] = m-b and x[n2]=m+c. You now want to choose n1 (and thus n2) so that b and c are as close as possible. This occurs when (b - c)**2 is minimal. That's pretty easy using numpy.argmin. Paralleling the example in the question, here's an interactive session illustrating the approach:
$ python
Python 2.6.5 (r265:79063, Jun 12 2010, 17:07:01)
[GCC 4.3.4 20090804 (release) 1] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> theList = np.log10(1+np.arange(.1, 100))
>>> theMedian = np.median(theList)
>>> listHead = theList[0:30]
>>> listTail = theList[-30:]
>>> b = np.abs(listHead - theMedian)
>>> c = np.abs(listTail - theMedian)
>>> squaredDiff = (b - c) ** 2
>>> np.argmin(squaredDiff)
25
>>> listHead[25] - theMedian, listTail[25] - theMedian
(-0.2874888056626983, 0.27859407466756614)
What you want is scipy.stats.mstats.trimboth. Set proportiontocut=0.15. After trimming, take (max-min)/2.

Categories