0

我有(由 SymPy 自动生成的)表达式,包括 sqrt 函数,在 sqrt 下有大数字,在它前面有小乘数。所以总体结果必须在浮点范围内,但 sqrt - 下的值不在。我使用 lambdify 命令将此表达式转换为 Python 函数。调用此函数得到异常:

from sympy import *
t = symbols("t")
k = 10
f = 2 * 10 ** (- k) * sqrt(10 ** (2 * k) * t ** 2 + 1)
print(f)
F = lambdify(t, f)
t0 = 10 ** 10
T = np.arange(t0, 2 * t0, t0 / 4)
print(T)
F(T)

输出:

2.0e-10*sqrt(100000000000000000000*t**2 + 1)
[1.00e+10 1.25e+10 1.50e+10 1.75e+10]
AttributeError: 'float' object has no attribute 'sqrt'

The above exception was the direct cause of the following exception:

TypeError                                 Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_15740/1035914544.py in <module>
      8 T = np.arange(t0, 2 * t0, t0 / 4)
      9 print(T)
---> 10 F(T)

<lambdifygenerated-11> in _lambdifygenerated(t)
      1 def _lambdifygenerated(t):
----> 2     return 2.0e-10*sqrt(100000000000000000000*t**2 + 1)

TypeError: loop of ufunc does not support argument 0 of type float which has no callable sqrt method

对于k = 2代码正常工作:

0.02*sqrt(10000*t**2 + 1)
[1.00e+10 1.25e+10 1.50e+10 1.75e+10]
array([2.0e+10, 2.5e+10, 3.0e+10, 3.5e+10])

有没有办法在不手动重写表达式的情况下解决这个问题?

UPD:看起来这是 NumPy 的问题:

import numpy as np
k = 10
def F1(t):
    return np.sqrt( (10 ** (- k)) ** 2 * 10 ** (2 * k) * t ** 2 + 1)
def F2(t):
    return 10 ** (- k) * np.sqrt(10 ** (2 * k) * t ** 2 + 1)
print(F1(10 ** 5))
print(F2(10 ** 5))

第一次通话有效,第二次通话 - 不!

4

2 回答 2

1

由于乘数很大,np.sqrt参数是对象 dtype 数组:

In [3]: 100000000000000000000 * T**2
Out[3]: array([1e+40, 1.5625e+40, 2.25e+40, 3.0625e+40], dtype=object)

使用对象 dtype 数组,numpy迭代(以列表理解速度),将“方法”应用于每个元素。有效

 1e+40.sqrt() etc

因此no method error.

你的修复:

In [3]: np.double(100000000000000000000 * T**2)
Out[3]: array([1.0000e+40, 1.5625e+40, 2.2500e+40, 3.0625e+40])

In [4]: np.sqrt(_)
Out[4]: array([1.00e+20, 1.25e+20, 1.50e+20, 1.75e+20])

或者

In [6]: np.sqrt((100000000000000000000 * T**2).astype(float))
Out[6]: array([1.00e+20, 1.25e+20, 1.50e+20, 1.75e+20])
于 2022-02-23T08:33:44.490 回答
1

将 np.sqrt 的参数转换为 numpy.double 可以解决问题:

def Sqrt(x):
  return np.sqrt(np.double(x))
F = lambdify(t, f, {'sqrt': Sqrt})
于 2022-02-23T08:26:48.527 回答