sin(y) 导致 "can't convert expression to float" 错误

sin(y) results in "can't convert expression to float" error

我创建了一个非常简单的 MWE 来说明我的问题。当我键入 y**(2) 时,程序运行。但是当我键入 sin(y)cos(y) 时,它会导致错误 TypeError: can't convert expression to float。我在下面讨论修复此错误的尝试。

    from vpython import *
    from scipy.optimize import fsolve
    import math
    import numpy as np
    import sympy as sp
    from sympy import Eq, Symbol, solve
    import matplotlib.pyplot as plt
    
    y = Symbol('y')
    
    i = input()
    i = ''.join(i).split(',')
    for x in range(0, len(i)):
        i[x] = i[x].strip()
    userMediums = i
    
    def refIndexSize(medium):
       
        def refractiveProfile(y):
                return eval(medium, {'y': y, 'np': np})
           
        lowerProfile = Eq(eval(medium), 1)
        upperProfile = Eq(eval(medium), 1.6)
        bounds = [abs(round(float(solve(lowerProfile)[0]),5)),
                  abs(round(float(solve(upperProfile)[0]),5))]
        lowerBound = np.amin(bounds)
        upperBound = np.amax(bounds)
       
        return lowerProfile
    
    refIndexSize(userMediums[0])

错误:


    sin(y)+1
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    /tmp/ipykernel_48/825631216.py in <module>
         29     return lowerProfile
         30 
    ---> 31 refIndexSize(userMediums[0])
    
    /tmp/ipykernel_48/825631216.py in refIndexSize(medium)
         20             return eval(medium, {'y': y, 'np': np})
         21 
    ---> 22     lowerProfile = eval(medium)
         23     upperProfile = Eq(eval(medium), 1.6)
         24     bounds = [abs(round(float(solve(lowerProfile)[0]),5)),
    
    <string> in <module>
    
    /srv/conda/envs/notebook/lib/python3.7/site-packages/sympy/core/expr.py in __float__(self)
        357         if result.is_number and result.as_real_imag()[1]:
        358             raise TypeError("can't convert complex to float")
    --> 359         raise TypeError("can't convert expression to float")
        360 
        361     def __complex__(self):
    
    TypeError: can't convert expression to float

我查看了有关 TypeError: can't convert expression to float 的其他问题,例如 and this。因此,我尝试更改导入的顺序,尽管我无法更改通配符 from vpython import *,因为这是导入 vpython 的唯一方法(据我所知),但这没有用。在查看了不同的 SO 答案后,我也尝试输入 sp.sin(y) ,但这也无济于事。再次感谢任何提示或帮助。

你的问题出在这一行:

bounds = [abs(round(float(solve(lowerProfile)[0]),5)),
              abs(round(float(solve(upperProfile)[0]),5))]

具体这部分:

abs(round(float(solve(upperProfile)[0]),5))

此处solve()函数returns列表中的复解。 看到这个:

[1.5707963267949 - 1.04696791500319*I, 1.5707963267949 + 1.04696791500319*I]

因此,当您选择 0 索引时,它将是一个复杂的结果,如下所示:

1.5707963267949 - 1.04696791500319*I

因此,您试图将 float() 强制转换为导致错误的解决方案。相反,您可以通过使用 try-except 块来删除具有复杂结果的解决方案的界限,如下所示:

try:
  bounds = [abs(round(float(solve(lowerProfile)[0]),5)),
              abs(round(float(solve(upperProfile)[0]),5))]
  lowerBound = np.amin(bounds)
  upperBound = np.amax(bounds)
except:
  print("The solutions are complex. Cant find a result")

也像这样导入:

from vpython import *
from scipy.optimize import fsolve
import math
import numpy as np
import sympy as sp
from sympy import *
import matplotlib.pyplot as plt

ipython 会话中,最相关的导入:

In [1]: import numpy as np
   ...: import sympy as sp
   ...: from sympy import Eq, Symbol, solve

将您的函数也修改为 return bounds

In [2]: def refIndexSize(medium):
   ...: 
   ...:         def refractiveProfile(y):
   ...:                 return eval(medium, {'y': y, 'np': np})
   ...: 
   ...:         lowerProfile = Eq(eval(medium), 1)
   ...:         upperProfile = Eq(eval(medium), 1.6)
   ...:         bounds = [abs(round(float(solve(lowerProfile)[0]),5)),
   ...:                   abs(round(float(solve(upperProfile)[0]),5))]
   ...:         lowerBound = np.amin(bounds)
   ...:         upperBound = np.amax(bounds)
   ...: 
   ...:         return lowerProfile, bounds
   ...: 

定义符号,用字符串调用函数。在交互式会话中,我不需要经历 input 并发症。

In [3]: y = sp.Symbol('y')

y**2 给出您在评论中声明的界限:

In [4]: refIndexSize("y**(2)")
Out[4]: (Eq(y**2, 1), [1.0, 1.26491])

由于 sin 定义而导致的错误

使用 sin 表达式给出 NameErrorsin 尚未导入或定义。

In [5]: refIndexSize("sin(y)+1")
Traceback (most recent call last):
  File "<ipython-input-5-30c99485bce7>", line 1, in <module>
    refIndexSize("sin(y)+1")
  File "<ipython-input-2-6fea36c332b7>", line 6, in refIndexSize
    lowerProfile = Eq(eval(medium), 1)
  File "<string>", line 1, in <module>
NameError: name 'sin' is not defined

math 导入 sin 给出了您的错误:

In [6]: from math import sin
In [7]: refIndexSize("sin(y)+1")
Traceback (most recent call last):
  File "<ipython-input-7-30c99485bce7>", line 1, in <module>
    refIndexSize("sin(y)+1")
  File "<ipython-input-2-6fea36c332b7>", line 6, in refIndexSize
    lowerProfile = Eq(eval(medium), 1)
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 359, in __float__
    raise TypeError("can't convert expression to float")
TypeError: can't convert expression to float

math.sin 需要一个浮点值,因此不适用于符号 y.

但是从 sympy 导入 sin,它起作用了:

In [8]: from sympy import sin
In [9]: refIndexSize("sin(y)+1")
Out[9]: (Eq(sin(y) + 1, 1), [0.0, 0.6435])

复杂值导致的错误

最初你的问题显示了 sin(y) 的使用,它给出了 @Prakash 讨论的 complex 错误

In [10]: refIndexSize("sin(y)")
Traceback (most recent call last):
  File "<ipython-input-10-d470e7448a68>", line 1, in <module>
    refIndexSize("sin(y)")
  File "<ipython-input-2-6fea36c332b7>", line 9, in refIndexSize
    abs(round(float(solve(upperProfile)[0]),5))]
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 358, in __float__
    raise TypeError("can't convert complex to float")
TypeError: can't convert complex to float

让我们简化您的函数以摆脱似乎有问题的 float 调用

In [11]: def refIndexSize(medium):
    ...:    lowerProfile = Eq(eval(medium), 1)
    ...:    upperProfile = Eq(eval(medium), 1.6)
    ...:    bounds = [solve(lowerProfile),
    ...:              solve(upperProfile)]
    ...:    return lowerProfile, bounds
    ...: 

运行 在 sin(y)+1) 上,我们像以前一样得到 [0.0, 0.6435] 值:

In [12]: refIndexSize("sin(y)+1")
Out[12]: (Eq(sin(y) + 1, 1), [[0, pi], [0.643501108793284, 2.49809154479651]])

运行 在 sin(y) 上,我们看到 'raw' 边界包括复数值:

In [13]: refIndexSize("sin(y)")
Out[13]: 
(Eq(sin(y), 1),
 [[pi/2],
  [1.5707963267949 - 1.04696791500319*I,
   1.5707963267949 + 1.04696791500319*I]])

如果你真的需要这样一个答案的四舍五入的浮点数,你需要先提取 real 部分,或者先使用 abs:

In [15]: bounds = _[1][1]
In [17]: abs(bounds[0])
Out[17]: 1.88773486361789