4

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.

Ryan
  • 1,040
  • 3
  • 16
  • 25
  • The calculation of limits is not implemented in python, for this you could use sympy: http://www.sympy.org/en/index.html – eyllanesc Mar 26 '17 at 04:45
  • you can use www.wolframalpha.com for calculating that – STF Mar 26 '17 at 04:46
  • you should learn about limits again. It's not like you substitute the value directly. What does `** math.inf` means? It doesn't make sense in normal arithmetics. Same to `1/0` or `1/math.inf`. They must be solved using limits – phuclv Mar 26 '17 at 05:08
  • Thanks for your input! I just updated my question to clarify my intention and please suggest if I can achieve that. @eyllanesc – Ryan Mar 26 '17 at 05:22
  • I think it is better to use the if statements. If `conversion_times` is too large (albeit unrealistically large for your application), you might start to have rounding errors with your floating point arithmetic. – rlee827 Mar 26 '17 at 05:57
  • Just FYI, when you add 1.0 to 1.0e-16 (or lower) you incur in a misalignment error (i.e. every time two floating points are misaligned by more than 16 digits, the lower number is not considered). Assuming that math.inf takes the maximum double precision number (around 10^308), what you are writing is just 1 ^ (10^308) = 1 – 7raiden7 Mar 29 '17 at 20:40

5 Answers5

6

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
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
3

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
Paul Panzer
  • 51,835
  • 3
  • 54
  • 99
1

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')
MuellerSeb
  • 796
  • 6
  • 11
0

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.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Ariel Ferdman
  • 124
  • 3
  • 11
0

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
v01d
  • 16
  • 3