如何从字符串绘制数学函数? [英] How to plot a math function from string?

查看:58
本文介绍了如何从字符串绘制数学函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个代表函数的字符串,例如"x *(x-32(2/x))" .我正在使用 matplotlib ,但是我不知道如何将此字符串转换为要绘制的点数组.

解决方案

您可以使用pythons eval 函数将字符串转换为代码,但这很危险,通常被认为是不好的风格,请参见:

对于恶意用户:

 输入函数:f(x)=导入子进程;subprocess.check_call(['rm','-rf','*'],shell = True)回溯(最近一次调用最后一次):< module>中的文件"test.py",第35行func = string2func(input('输入函数:f(x) = '))string2func中的文件"test.py",第22行'"{}" 禁止在数学表达式中使用'.format(word)ValueError:禁止在数学表达式中使用导入"

第一个版本 - 黑名单危险词:

将 numpy 导入为 np导入matplotlib.pyplot作为plt#应该有使用regex的更好方法替换 = {'罪':'np.sin','cos':'np.cos','exp': 'np.exp','^':'**',}# 想到这里更多的安全隐患forbidden_​​words = ['进口','shutil','系统','子进程',]def string2func(字符串):'''计算字符串并返回x的函数'''forbidden_​​words 中的单词:如果字符串中的单词:引发ValueError('"{}" 禁止在数学表达式中使用'.format(word))对于replaces.items() 中的旧的、新的:字符串= string.replace(旧,新)def func(x):返回eval(字符串)返回函数

I have a string which represents a function, like "x * (x - 32 ( 2 /x) )". I'm using matplotlib, but I don't know how convert this string into an array of points to plot.

解决方案

You can turn a string into code by using pythons eval function, but this is dangerous and generally considered bad style, See this: https://stackoverflow.com/a/661128/3838691. If user can input the string, they could input something like import subprocess; subprocess.check_call(['rm', '-rf', '*'], shell=True).

So be sure that you build in reasonable security into this.

You can define a function that takes a string and returns a function. We need to do a little preprocessing to allow the user to input formulas more like he is used to (^ etc.):

Edit: Second version – white list instead of blacklist

It seems better to define allowed and supported words than blacklisting some:

import re

replacements = {
    'sin' : 'np.sin',
    'cos' : 'np.cos',
    'exp': 'np.exp',
    'sqrt': 'np.sqrt',
    '^': '**',
}

allowed_words = [
    'x',
    'sin',
    'cos',
    'sqrt',
    'exp',
]

def string2func(string):
    ''' evaluates the string and returns a function of x '''
    # find all words and check if all are allowed:
    for word in re.findall('[a-zA-Z_]+', string):
        if word not in allowed_words:
            raise ValueError(
                '"{}" is forbidden to use in math expression'.format(word)
            )

    for old, new in replacements.items():
        string = string.replace(old, new)

    def func(x):
        return eval(string)

    return func


if __name__ == '__main__':

    func = string2func(input('enter function: f(x) = '))
    a = float(input('enter lower limit: '))
    b = float(input('enter upper limit: '))
    x = np.linspace(a, b, 250)

    plt.plot(x, func(x))
    plt.xlim(a, b)
    plt.show()

Result:

$ python test.py
enter function: f(x) = x^2
enter lower limit: 0
enter upper limit: 2

And for a malicious user:

enter function: f(x) = import subprocess; subprocess.check_call(['rm', '-rf', '*'], shell=True)
Traceback (most recent call last):
  File "test.py", line 35, in <module>
    func = string2func(input('enter function: f(x) = '))
  File "test.py", line 22, in string2func
    '"{}" is forbidden to use in math expression'.format(word)
ValueError: "import" is forbidden to use in math expression

Edit: First version – blacklist hazardous words:

import numpy as np
import matplotlib.pyplot as plt

# there should be a better way using regex
replacements = {
    'sin' : 'np.sin',
    'cos' : 'np.cos',
    'exp': 'np.exp',
    '^': '**',
}

# think of more security hazards here
forbidden_words = [
    'import',
    'shutil',
    'sys',
    'subprocess',
]

def string2func(string):
    ''' evaluates the string and returns a function of x '''
    for word in forbidden_words:
        if word in string:
            raise ValueError(
                '"{}" is forbidden to use in math expression'.format(word)
            )

    for old, new in replacements.items():
        string = string.replace(old, new)

    def func(x):
        return eval(string)

    return func

这篇关于如何从字符串绘制数学函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆