简体   繁体   中英

How to force Python give solutions instead of 'Nan', e.g. large input in scipy.special import kn

I notice python avoid calculating some extreme value, for example kn(2,x>600) = Nan , how could force python to provide a value instead of 'Nan'?

在此处输入图像描述

import numpy as np
from scipy.special import kn
import matplotlib.pyplot as plt
x = np.logspace(0, 3, 100)
plt.plot(x, kn(2, x), label='$K_2(x)$')
plt.ylim(0, 10)
plt.yscale('log')
plt.xscale('log')
plt.legend()
plt.title(r'Modified Bessel function of the second kind $K_2(x)$')
plt.show()

You're running up against machine precision here. Check out the actual values for a different range:

x = np.logspace(2.5, 3, 100)
y = kn(2, x)
print(y)

yields

array([3.27082355e-139, 8.04765930e-141, 1.89623338e-142, 4.27665221e-144,
       9.22749139e-146, 1.90373267e-147, 3.75355921e-149, 7.06911929e-151,
       1.27098118e-152, 2.18036409e-154, 3.56694629e-156, 5.56161008e-158,
       8.26032006e-160, 1.16798880e-161, 1.57136165e-163, 2.01028012e-165,
       2.44412995e-167, 2.82241343e-169, 3.09374066e-171, 3.21698746e-173,
       3.17138653e-175, 2.96218619e-177, 2.61977955e-179, 2.19244653e-181,
       1.73510013e-183, 1.29767955e-185, 9.16580410e-188, 6.11002951e-190,
       3.84141931e-192, 2.27624181e-194, 1.27034732e-196, 6.67266861e-199,
       3.29641352e-201, 1.53051400e-203, 6.67376973e-206, 2.73101779e-208,
       1.04803219e-210, 3.76873070e-213, 1.26898290e-215, 3.99781360e-218,
       1.17749058e-220, 3.23980250e-223, 8.32070057e-226, 1.99311122e-228,
       4.44917394e-231, 9.24794484e-234, 1.78840827e-236, 3.21497095e-239,
       5.36791283e-242, 8.31718958e-245, 1.19484297e-247, 1.59009856e-250,
       1.95851837e-253, 2.23063495e-256, 2.34708527e-259, 2.27943049e-262,
       2.04133304e-265, 1.68414524e-268, 1.27881202e-271, 8.92840360e-275,
       5.72604000e-278, 3.36989935e-281, 1.81813009e-284, 8.98331910e-288,
       4.06074540e-291, 1.67756649e-294, 6.32705298e-298, 2.17624754e-301,
       6.81917993e-305, 0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
       0.00000000e+000, 0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
       0.00000000e+000, 0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
       0.00000000e+000, 0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
       0.00000000e+000, 0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
       0.00000000e+000, 0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
       0.00000000e+000, 0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
       0.00000000e+000, 0.00000000e+000, 0.00000000e+000, 0.00000000e+000])

The smallest floating point number that can be represented is about 2.225e-308 (see here ). So numbers smaller than that are set to identically 0 by python. There is no "forcing python to give solutions". Your NaN issues are coming from trying to take the log of 0 while plotting.

According to the answers in the post Bessel functions in Python that work with large exponents we should have two ways to get Bessel extreme results

  1. the exponential bessel function scipy.special.kve
  2. the mpmath library mpmath.besselk for second kind kn

But we can only use logarithm results

import numpy as np
from math import e
from scipy.special import kn,kv,kve
import matplotlib.pyplot as plt
import mpmath

x = np.logspace(0, 3, 100)
y = kn(2,x)
y2 = kv(2,x)
## kve(v, z) = kv(v, z) * exp(z)
y3 = np.log10(kve(2,x)) - x*np.log10(e)

y4 = []
for i in x:
  yy = mpmath.besselk(2,i)
  yy = mpmath.mp.log10(yy)
  y4.append(yy)

x = np.log10(x)
y = np.log10(y)
y2 = np.log10(y2)

plt.plot(x, y, lw = 7, label=r'$K_2(x)$ by kn')
plt.plot(x, y2, lw = 9, ls='--', label=r'$K_v(2,x)$ by kv')
plt.plot(x, y3, lw = 3, ls='--', label=r'$K_v(2,x)$ by kve')
plt.plot(x, y4, ls='-', label=r'$K_2(x)$ by mpmath')

plt.title(r'Modified Bessel function of the second kind $K_2(x)$')
plt.xlabel('log x')
plt.ylabel('log y')
plt.legend()

plt.tight_layout()
plt.savefig('kn.png',format='png')
plt.show()

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM