函数图像绘制方法、装置、设备及计算机存储介质与流程

文档序号:14008275阅读:166来源:国知局
函数图像绘制方法、装置、设备及计算机存储介质与流程

本发明涉及绘制技术领域,尤其涉及函数图像绘制方法、装置、设备及计算机存储介质。



背景技术:

在实际应用中往往需要绘制输入函数对应的函数图像,为此可以将用户输入的输入函数进行解析,并绘制输入函数对应的函数图像。目前,可以采用逆波兰表示法将用户输入的输入函数进行解析。在逆波兰表示法中,每一运算符都置于其运算对象之后。将输入函数解析成逆波兰表达式后,根据解析获得的表达式以及输入值,如果当前字符为自变量或者数字,则压栈,如果当前字符是运算符,则将栈顶两个元素弹出作相应运算,将运算结果再入栈,最后在表达式扫描完后,栈顶的值即为函数值。然而,该方法仅能满足基本的加减乘除,针对包含对数运算符等复杂运算符的输入函数,无法将输入函数转换为逆波兰表达式的方式,进而无法实现函数图像绘制。



技术实现要素:

本发明提供了函数图像绘制方法、装置、设备及计算机存储介质,以解决现有技术中针对包含复杂运算符的输入函数无法实现函数图像绘制的缺陷。

根据本发明实施例的第一方面,提供一种函数图像绘制方法,所述方法包括:

获得输入函数;

将所述输入函数进行解析,获得所述输入函数的组成结构,其中,所述组成结构中,所述输入函数由至少一个当前层预定义函数构成,当前层预定义函数为指定数或非指定数的当前层预定义函数,非指定数的当前层预定义函数被解析为由下一层预定义函数基于运算符或括号构成,直到底层预定义函数为指定数,所述指定数包括数值、自变量和数学常数;

基于所述组成结构执行输入函数中的运算符,其中,若运算符的运算对象为非指定数的预定义函数,则根据所述组成结构计算该预定义函数的值,并根据值和运算符获得运算结果,执行完所有运算符后获得所述输入函数中输入值对应的函数值;

利用由所述输入值和所述函数值构成的点坐标绘制所述输入函数对应的函数图像。

在一个可选的实现方式中,所述将所述输入函数进行解析,获得所述输入函数的组成结构,包括:

将所述输入函数按预设分类进行字符串分割,所述预设分类包括指定数类和运算符类;

调用读取策略对分割获得的字符串进行解析,获得所述输入函数的组成结构,所述读取策略包括:

从左到右依次读取分割获得的字符串;

若当前读取的字符串为指定数,将所述指定数作为当前层预定义函数;

若当前读取的字符串为运算符,基于运算符确定需要向右读取的字符串,并将所读取的字符串以及所述运算符确定为当前层预定义函数,基于所读取的字符串确定下一层预定义函数;

若当前读取的字符串为左括号,则调用所述读取策略从左到右依次读取括号内的字符串,直到读取到右括号,基于括号内的字符串确定下一层预定义函数。

在一个可选的实现方式中,所述将所述输入函数按预设分类进行字符串分割之前,还包括对所述输入函数进行预处理;

所述对所述输入函数进行预处理,包括以下一种或多种处理:

判断所述输入函数中括号是否成对出现,若括号没有成对出现,则报错;

判断所述输入函数中是否存在不合法字符,若存在不合法字符,则报错;

判断所述输入函数中是否存在相邻的运算符,若存在相邻的加号和减号,则删除加号;若存在相邻的至少两个加号,则保留其中一个加号;若存在相邻的至少两个减号,则当减号个数为基数时,则保留其中一个减号,当减号个数为偶数时,则将该相邻减号替换为一个加号;

判断所述输入函数中是否存在空格,若存在空格,则删除空格;

判断所述输入函数中是否存在省略的乘号,若存在,则在省略乘号的位置处添加乘号;

将所述输入函数中的字母统一变更为大写字母或小写字母。

在一个可选的实现方式中,所述直到解析获得的预定义函数为指定数后,还包括:

判断所述输入函数中是否存在指定运算符,所述指定运算符包括乘号、除号和次方运算符;

若存在指定运算符,则按指定运算符的优先级将优先级高的指定运算符以及其所需的运算对象构成的函数作为相邻运算符所在层预定义函数的下一层预定义函数。

在一个可选的实现方式中,所述利用由所述输入值和所述函数值构成的点坐标绘制所述输入函数对应的函数图像,包括:

采用预设绘制策略对相邻点构成的线段进行绘制和判断,所有点绘制和判断完成后,获得所述输入函数对应的函数图像;所述点基于输入值和函数值构成的点坐标获得;

所述预设绘制策略包括:

绘制由相邻点的第一点和第二点构成的线段;

取所述线段的中点,获得中点坐标;

将中点坐标中的横坐标作为输入函数的输入值,获得输入值对应的函数值;

比较由输入值和函数值构成的目标点与中点的距离;

若所述距离小于指定阈值,则进行下一线段的绘制和判断;

若所述距离大于或等于指定阈值,则删除所述线段,并利用所述预设绘制策略对由第一点和目标点构成的线段进行绘制和判断、以及利用所述预设绘制策略对由目标点和第二点构成的线段进行绘制和判断。

根据本发明实施例的第二方面,提供一种函数图像绘制装置,所述装置包括:

函数获取模块,用于获得输入函数;

结构获得模块,用于将所述输入函数进行解析,获得所述输入函数的组成结构,其中,所述组成结构中,所述输入函数由至少一个当前层预定义函数构成,当前层预定义函数为指定数或非指定数的当前层预定义函数,非指定数的当前层预定义函数被解析为由下一层预定义函数基于运算符或括号构成,直到底层预定义函数为指定数,所述指定数包括数值、自变量和数学常数;

函数运算模块,用于基于所述组成结构执行输入函数中的运算符,其中,若运算符的运算对象为非指定数的预定义函数,则根据所述组成结构计算该预定义函数的值,并根据值和运算符获得运算结果,执行完所有运算符后获得所述输入函数中输入值对应的函数值;

图像绘制模块,用于利用由所述输入值和所述函数值构成的点坐标绘制所述输入函数对应的函数图像。

在一个可选的实现方式中,所述结构获得模块用于:

将所述输入函数按预设分类进行字符串分割,所述预设分类包括指定数类和运算符类;

调用读取策略对分割获得的字符串进行解析,获得所述输入函数的组成结构,所述读取策略包括:

从左到右依次读取分割获得的字符串;

若当前读取的字符串为指定数,将所述指定数作为当前层预定义函数;

若当前读取的字符串为运算符,基于运算符确定需要向右读取的字符串,并将所读取的字符串以及所述运算符确定为当前层预定义函数,基于所读取的字符串确定下一层预定义函数;

若当前读取的字符串为左括号,则调用所述读取策略从左到右依次读取括号内的字符串,直到读取到右括号,基于括号内的字符串确定下一层预定义函数。

在一个可选的实现方式中,所述装置还包括预处理模块,用于:将所述输入函数按预设分类进行字符串分割之前,对所述输入函数进行预处理;

所述对所述输入函数进行预处理,包括以下一种或多种处理:

判断所述输入函数中括号是否成对出现,若括号没有成对出现,则报错;

判断所述输入函数中是否存在不合法字符,若存在不合法字符,则报错;

判断所述输入函数中是否存在相邻的运算符,若存在相邻的加号和减号,则删除加号;若存在相邻的至少两个加号,则保留其中一个加号;若存在相邻的至少两个减号,则当减号个数为基数时,则保留其中一个减号,当减号个数为偶数时,则将该相邻减号替换为一个加号;

判断所述输入函数中是否存在空格,若存在空格,则删除空格;

判断所述输入函数中是否存在省略的乘号,若存在,则在省略乘号的位置处添加乘号;

将所述输入函数中的字母统一变更为大写字母或小写字母。

在一个可选的实现方式中,所述装置还包括优先级处理模块,用于:

判断所述输入函数中是否存在指定运算符,所述指定运算符包括乘号、除号和次方运算符;

若存在指定运算符,则按指定运算符的优先级将优先级高的指定运算符以及其所需的运算对象构成的函数作为相邻运算符所在层预定义函数的下一层预定义函数。

在一个可选的实现方式中,所述图像绘制模块用于:

采用预设绘制策略对相邻点构成的线段进行绘制和判断,所有点绘制和判断完成后,获得所述输入函数对应的函数图像;所述点基于输入值和函数值构成的点坐标获得;

所述预设绘制策略包括:

绘制由相邻点的第一点和第二点构成的线段;

取所述线段的中点,获得中点坐标;

将中点坐标中的横坐标作为输入函数的输入值,获得输入值对应的函数值;

比较由输入值和函数值构成的目标点与中点的距离;

若所述距离小于指定阈值,则进行下一线段的绘制和判断;

若所述距离大于或等于指定阈值,则删除所述线段,并利用所述预设绘制策略对由第一点和目标点构成的线段进行绘制和判断、以及利用所述预设绘制策略对由目标点和第二点构成的线段进行绘制和判断。

根据本发明实施例的第三方面,提供一种电子设备,包括:

处理器;

用于存储处理器可执行指令的存储器;

其中,所述处理器被配置为:

获得输入函数;

将所述输入函数进行解析,获得所述输入函数的组成结构,其中,所述组成结构中,所述输入函数由至少一个当前层预定义函数构成,当前层预定义函数为指定数或非指定数的当前层预定义函数,非指定数的当前层预定义函数被解析为由下一层预定义函数基于运算符或括号构成,直到底层预定义函数为指定数,所述指定数包括数值、自变量和数学常数;

基于所述组成结构执行输入函数中的运算符,其中,若运算符的运算对象为非指定数的预定义函数,则根据所述组成结构计算该预定义函数的值,并根据值和运算符获得运算结果,执行完所有运算符后获得所述输入函数中输入值对应的函数值;

利用由所述输入值和所述函数值构成的点坐标绘制所述输入函数对应的函数图像。

根据本发明实施例的第四方面,提供一种计算机存储介质,所述存储介质中存储有程序指令,所述程序指令包括:

获得输入函数;

将所述输入函数进行解析,获得所述输入函数的组成结构,其中,所述组成结构中,所述输入函数由至少一个当前层预定义函数构成,当前层预定义函数为指定数或非指定数,非指定数的当前层预定义函数被解析为由下一层预定义函数基于运算符或括号构成,直到底层预定义函数为指定数,所述指定数包括数值、自变量和数学常数;

基于所述组成结构执行输入函数中的运算符,其中,若运算符的运算对象为非指定数的预定义函数,则根据所述组成结构计算该预定义函数的值,并根据值和运算符获得运算结果,执行完所有运算符后获得所述输入函数中输入值对应的函数值;

利用由所述输入值和所述函数值构成的点坐标绘制所述输入函数对应的函数图像。

本发明的实施例提供的技术方案可以包括以下有益效果:

本发明实施例可以在获得输入函数后,将输入函数进行解析,获得输入函数的组成结构。在输入函数的组成结构中,可以将输入函数看作由至少一个当前层预定义函数构成,当前层预定义函数相当于输入函数的子函数,当前层预定义函数可以是指定数,也可以是非指定数的当前层预定义函数(可以称为非指定数)。如果存在非指定数的当前层预定义函数,非指定数的当前层预定义函数可以解析成由至少一个下一层预定义函数基于运算符或括号构成,以此类推,直到解析获得的预定义函数为指定数,指定数可以是数值、自变量和数学常量。通过解析,将输入函数拆分为由指定数的预定义函数和非指定数的预定义函数构成,以便在执行运算符时,如果运算符的运算对象是非指定数的预定义函数,则先求解非指定数的预定义函数的值,再进行运算符运算,从而获得输入函数的函数值,进而利用由输入值和函数值构成的点坐标绘制输入函数对应的函数图像。因此,采用本说明书实施例方案,不对运算符进行限制,可以适用于多种运算符,扩大了绘制函数图像的范围。

应当理解的是,以上的一般描述和后文的细节描述仅是示例性和解释性的,并不能限制本发明。

附图说明

此处的附图被并入说明书中并构成本说明书的一部分,示出了符合本发明的实施例,并与说明书一起用于解释本发明的原理。

图1是本发明根据一示例性实施例示出的一种函数图像绘制方法的流程图。

图2是本发明根据一示例性实施例示出的一种函数组成结构示意图。

图3是本发明根据一示例性实施例示出的另一种函数组成结构示意图。

图4是本发明根据一示例性实施例示出的一种函数图像绘制装置的框图。

图5是本发明根据一示例性实施例示出的一种函数图像绘制装置所在电子设备的一种硬件结构图。

具体实施方式

这里将详细地对示例性实施例进行说明,其示例表示在附图中。下面的描述涉及附图时,除非另有表示,不同附图中的相同数字表示相同或相似的要素。以下示例性实施例中所描述的实施方式并不代表与本发明相一致的所有实施方式。相反,它们仅是与如所附权利要求书中所详述的、本发明的一些方面相一致的装置和方法的例子。

在本发明使用的术语是仅仅出于描述特定实施例的目的,而非旨在限制本发明。在本发明和所附权利要求书中所使用的单数形式的“一种”、“所述”和“该”也旨在包括多数形式,除非上下文清楚地表示其他含义。还应当理解,本文中使用的术语“和/或”是指并包含一个或多个相关联的列出项目的任何或所有可能组合。

应当理解,尽管在本发明可能采用术语第一、第二、第三等来描述各种信息,但这些信息不应限于这些术语。这些术语仅用来将同一类型的信息彼此区分开。例如,在不脱离本发明范围的情况下,第一信息也可以被称为第二信息,类似地,第二信息也可以被称为第一信息。取决于语境,如在此所使用的词语“如果”可以被解释成为“在……时”或“当……时”或“响应于确定”。

本发明实施例可以应用中各种需要进行函数图像绘制的电子设备中,例如,可以是交互智能平板、数位板等智能书写设备,也可以是具备绘图功能的智能手机、智能学习机、平板电脑、pda(personaldigitalassistant,个人数字助理)等电子设备,当然,本发明实施例也不排除在pc(personalcomputer,个人计算机)上的应用。

在实际应用中往往需要绘制输入函数对应的函数图像。例如,用户在教学、会议等过程中可以写入输入函数,通过电子设备绘制输入函数转对应的函数图像,以便用户结合函数图像进行讲解。目前,可以采用逆波兰表示法将用户输入的输入函数进行解析。在逆波兰表示法中,每一运算符都置于其运算对象之后。例如,将“5+((x+2)*4)-3”解析为“5x2+4*+3-”。将输入函数解析成逆波兰表达式后,对自变量进行赋值,获得输入值,根据解析获得的表达式以及输入值,如果当前字符为自变量或者数字,则压栈,如果当前字符是运算符,则将栈顶两个元素弹出作相应运算,将运算结果再入栈,最后当表达式扫描完后,栈顶的值即为函数值。然而,该方法仅能满足基本的加减乘除,针对包含对数运算符等复杂运算符的输入函数,无法将输入函数转换为逆波兰表达式的方式,进而无法实现函数图像绘制。

本发明实施例所提供的方案,可以在获得输入函数后,将输入函数进行解析,获得输入函数的组成结构。在输入函数的组成结构中,可以将输入函数看作由第一层预定义函数构成,第一层预定义函数相当于输入函数的子函数,第一层预定义函数可以是指定数,也可以非指定数。其中,非指定数可以是指不是指定数的预定义函数。如果存在非指定数的第一层预定义函数,非指定数的第一层预定义函数可以解析成由至少一个第二层预定义函数基于运算符或括号构成。第二层预定义函数与第一层预定义函数的定义相同,第二层预定义函数相当于第一层预定义函数的子函数,第二层预定义函数可以是指定数,也可以是非指定数,如果存在第二层预定义函数不是指定数,则非指定数的第二层预定义函数进行进一步解析,直到解析获得的预定义函数为指定数,指定数可以是数值、自变量和数学常量。通过解析,将输入函数拆分为由指定数的预定义函数和非指定数的预定义函数构成,以便在执行运算符时,如果运算符的运算对象是非指定数的预定义函数,则先求解非指定数的预定义函数的值,再进行运算符运算,从而获得输入函数的函数值,进而利用由输入值和函数值构成的点坐标绘制输入函数对应的函数图像。因此,采用本说明书实施例方案,不对运算符进行限制,可以适用于多种运算符,扩大了绘制函数图像的范围。

接下来结合附图对本发明方案进行示例说明。

如图1所示,图1是本发明根据一示例性实施例示出的一种函数图像绘制方法的流程图,该方法可以包括以下步骤101至步骤104:

在步骤101中,获得输入函数;

在步骤102中,将所述输入函数进行解析,获得所述输入函数的组成结构,其中,所述组成结构中,所述输入函数由至少一个当前层预定义函数构成,当前层预定义函数为指定数或非指定数,非指定数的当前层预定义函数被解析为由下一层预定义函数基于运算符或括号构成,直到底层预定义函数为指定数,所述指定数包括数值、自变量和数学常数;

在步骤103中,基于所述组成结构执行输入函数中的运算符,其中,若运算符的运算对象为非指定数的预定义函数,则根据所述组成结构计算该预定义函数的值,并根据值和运算符获得运算结果,执行完所有运算符后获得所述输入函数中输入值对应的函数值;

在步骤104中,利用由所述输入值和所述函数值构成的点坐标绘制所述输入函数对应的函数图像。

本实施例中,输入函数可以是包含自变量、因变量以及等号的函数,例如,f(x)=sinx+1,输入函数也可以是由字符串构成的表达式,例如,1+2+sin(x+1)+3x。输入函数的表现形式可以根据用户输入习惯进行设置,在此不做限制。

在一个例子中,用户可以通过键盘等非手写输入方式输入该输入函数,设备可以根据输入指令直接获得输入函数。而在另一个例子中,如果用户通过手写输入方式输入该输入函数,则可以利用字符识别算法对手写函数进行字符识别,获得输入函数。

其中,字符可以包括字母、数字、字和符号等。字符识别算法是用于将字符轨迹识别为相应字符的算法。例如,可以根据书写轨迹生成书写图案,基于模板匹配算法将字符轨迹识别为具体的字符。具体的,可以在字符数据库中查找与书写图案匹配的字符样本图案,若找到匹配的字符样本图案,则将书写图案识别为找到的字符样本图案对应的字符。其中,在查找与书写图案相匹配的字符样本图案的过程中,若存在多个匹配的字符样本图案,则可以计算各匹配字符样本图案的匹配度,并选取匹配度最高的字符样本图案作为找到匹配的字符样本图案。字符样本图案是由字符轨迹构成的图案,在字符数据库中存储有每个字符对应的至少一个字符样本图案。字符样本图案可以从其他网络数据库中获取,也可以基于书写设备的用户的书写笔迹获得。例如,根据用户的历史字符轨迹,建立字符轨迹与字符的对应关系,获得字符样本图案。应当理解的是,本说明书方案不限于上述所提及字符识别算法,还可以是其他字符识别算法,在此不一一列举。

在获得输入函数后,将所述输入函数进行解析,以获得所述输入函数的组成结构。在本实施例中提出一种结构划分方式:一个输入函数可以看作由至少一个当前层预定义函数构成,而当前层预定义函数可以是指定数,也可以不是指定数。将不是指定数的当前层预定义函数称为非指定数的当前层预定义函数。非指定数的当前层预定义函数又可以看作由至少一个下一层预定义函数基于运算符或括号构成。无论哪层预定义函数,若属于非指定数,则非指定数的预定义函数会被解析,直到最后解析获得的预定义函数为指定数。可以理解的是,当前层预定义函数和下一层预定义函数都是预定义函数,只是为了区分不同的预定义函数而进行不同的命名。

可见,在组成结构中,所述输入函数由至少一个第一层预定义函数构成,第一层预定义函数为指定数,或者由至少一个第二层预定义函数基于运算符或括号构成;

若存在第二层预定义函数,第二层预定义函数为指定数,或者由至少一个第三层预定义函数基于运算符或括号构成;

若存在第n-1层预定义函数,第n-1层预定义函数为指定数,或者由至少一个第n层预定义函数基于运算符或括号构成;

若存在第n层预定义函数,第n层预定义函数为指定数,指定数包括数值、自变量和数学常数。n为大于1的整数。

由于指定数可以是数值、自变量和数学常数,指定数可以直接作为运算符的运算对象进行运算,而非指定数的预定义函数不能直接作为运算符的运算对象进行运算,所以需要将非指定数的预定义函数进行进一步解析,直到解析为能作为运算符的运算对象,以实现在后续执行输入函数中的运算符时,能确定是否能利用运算符和运算对象进行运算,若能进行运算时,直接进行运算,获得该运算符的运算结果;若不能进行运算时,先计算运算对象的值,再基于获得的值和运算符进行运算,获得该运算符的运算结果。在所有运算符都执行后,可以获得每个输入值对应的函数值。

为了方便理解本说明书实施例对函数的划分方式,本实施例提供两种具体示例进行说明。如图2所示,图2是本发明根据一示例性实施例示出的一种函数组成结构示意图。在该示意图中,输入函数为:1+2+sin(x+1)

将输入函数划分为3个第一层预定义函数,函数1为:1,函数2为:+2,函数3为:+sin(x+1)

由于函数1:“1”为数值,则无需再对函数1进行解析;由于函数2:“+2”不是指定数,则函数2可以解析为由第二层预定义函数(简称函数2.1)“2”基于运算符+构成;由于函数3:+sin(x+1)不是指定数,则函数3可以解析为由第二层预定义函数(简称函数3.1)“sin(x+1)”基于运算符+构成;因此,函数2.1为:2,函数3.1为:sin(x+1)。

由于函数2.1:“2”为数值,则无需再对函数2.1进行解析;由于函数3.1:sin(x+1)不是指定数,则函数3.1可以解析为由第三层预定义函数(简称3.11)(x+1)基于运算符sin构成;因此,函数3.11为:(x+1)。

由于函数3.11:(x+1)不是指定数,则函数3.11可以解析为由两个第四层预定义函数(函数3.111为x,函数3.112为+1)基于括号构成;因此,函数3.111为:x,函数3.112为:+1。

由于+1不是指定数,则函数3.112可以解析为由第五层预定义函数(简称函数3.1121)“1”基于运算符+构成;因此函数3.1121为1。

鉴于此,可以得到如下组成结构:

第一层预定义函数:函数1是1;函数2是+2;函数3是+sin(x+1)。

第二层预定义函数:函数2.1是2;函数3.1是sin(x+1)。

第三层预定义函数:函数3.1.1是(x+1)。

第四层预定义函数:函数3.1.1.1是x,函数3.1.1.2是+1。

第五层预定义函数:函数3.1.1.2.1是1。

由于第三层预定义函数和第四层预定义函数表达的意义相同,所以往往可以省略一个,获得如图2所示组成结构,省略第三层预定义函数。

可以理解的是,若将每个层预定义函数作为一个节点函数,在输入函数的组成结构中,输入函数可以由至少一个节点函数构成,节点函数可以为指定数,或者由至少一个下一节点函数基于运算符或括号构成,其中,将为指定数的节点函数作为叶子节点函数。如图2所示,函数1、函数2.1、函数3.111和函数3.1121为叶子节点函数。

如图3所示,图3是本发明根据一示例性实施例示出的另一种函数组成结构示意图。在该示意图中,输入函数为:(1+x)*2+π,可以得到如下组成结构:

第一层预定义函数:函数1是(1+x);函数2是*2;函数3是+π。

第二层预定义函数:函数1.1是1,函数1.2是+x;函数2.1是2,函数3.1是π。

第三层预定义函数:函数1.21是x。

在一个可选的实现方式中,本发明实施例还列举一种具体的解析手段。所述将所述输入函数进行解析,获得所述输入函数的组成结构,包括:

将所述输入函数按预设分类进行字符串分割,所述预设分类包括指定数类和运算符类;

调用读取策略对分割获得的字符串进行解析,获得所述输入函数的组成结构。

本实施例中,为了将输入函数整理成便于解析的格式,可以先将输入函数按预设分类进行字符串分割。其中,预设分类可以包括指定数类和运算符类。指定数类是指定数所在分类,例如,可以是数值,自变量和数学常量。数值可以是1、log5等数值。自变量可以是字母,例如x。数学常量可以是圆周率π、自然对数的底e等特殊字符。运算符类是运算符所在分类,例如,可以是“+”、“-”、“*”、“/”“log”“sin”“tan”等。将每个指定数或运算符作为一条字符串,例如“tan”为一条字符串。

可以理解的是,输入函数中除了指定数和运算符,还可能包括其他字符,则将其他字符也进行分割。例如,还可能存在字符“(”、“)”、“,”等字符,针对这类既不是指定数,也不是运算符的字符也需要进行分割。例如,可以将输入函数1+2+sin(x+1)+3*x分割为如下字符串:

1,+,2,+,sin,(,x,+,1,),+,3,*,x。

其中,每条字符串用逗号分开。

进一步的,由于可能存在输入不合法的输入函数,鉴于此,将所述输入函数按预设分类进行字符串分割之前,还包括对所述输入函数进行预处理,以便在存在错误时及时报错,或者将不合法输入函数变更为合法输入。本实施例列举几种预处理手段。例如,所述对所述输入函数进行预处理,包括以下一种或多种处理:

判断所述输入函数中括号是否成对出现,若括号没有成对出现,则报错;

判断所述输入函数中是否存在不合法字符,若存在不合法字符,则报错;

判断所述输入函数中是否存在相邻的运算符,若存在相邻的加号和减号,则删除加号;若存在相邻的至少两个加号,则保留其中一个加号;若存在相邻的至少两个减号,则当减号个数为基数时,则保留其中一个减号,当减号个数为偶数时,则将相邻的至少两个减号替换为一个加号;

判断所述输入函数中是否存在空格,若存在空格,则删除空格;

判断所述输入函数中是否存在省略的乘号,若存在,则在省略乘号的位置处添加乘号;

将所述输入函数中的字母统一变更为大写字母或小写字母。

其中,括号没有成对出现可能会影响运算优先级,因此需要进行报错。报错方式可以是音频报警,或显示报警等方式。判断括号是否成对,可以根据左括号数量是否与右括号数量一致的方式进行判断,若左括号数量与右括号数量相同,可以判定括号成对出现,若左括号数量与右括号数量不同,可以判定括号没有成对出现。

关于不合法字符,可以预先规定不合法字符的类型,通过字符识别的方式判断输入函数中是否存在不合法字符。例如,规定中文字符为不合法字符,在识别到输入函数中包含中文字符时判定输入函数存在不合法字符。另一个例子中,也可以预先规定合法字符的范围,如果输入函数中的字符不在合法字符的范畴内,则判定输入函数存在不合法字符。可以理解的是,还可以通过其他手段判断输入函数是否存在不合法字符,在此不一一列举。

关于相邻运算符,在预处理中,还可以判断输入函数中是否存在相邻的运算符,针对某些相邻运算符可以直接进行运算,为了提高后续执行效率,可以将相邻运算符进行删减或变更。例如,相邻的加号和减号,实际结果是减号,因此可以删除加号。又如,存在多个相邻加号时,可以仅保留一个加号。又如,存在多个相邻减号时,当减号个数为基数时,则保留其中一个减号,当减号个数为偶数时,则将相邻的多个减号替换为一个加号。

例如,str=str.replace("+-","-");

str=str.replace("-+","-");

str=str.replace("--","+");

可见,将一些重复的运算符进行删减或变更,可以提高后续解析效率以及计算函数值效率。

如果在输入函数中存在空格,可以将空格删除。例如,str=str.replace("","")。

如果在输入函数中存在省略的乘号,可以添加省略的乘号。本实施例列举几种乘号添加判断方式判断是否需要添加乘号:

1.指定数后的字符为左括号,则在指定数和左括号之间添加乘号。如,1(2)可以变更为:1*(2)。

2.右括号后的字符为指定数,则在右括号和指定数之间添加乘号。如,(x+1)x可以变更为:(x+1)*x。

3.一类指定数后有另一类指定数,即相邻指定数为不同类指定数,则在两类指定数之间添加乘号。如,5x可以变更为:5*x。

4.指定数后有指定运算符,则在指定数后指定运算符之间添加乘号。指定运算符可以是sin、cos、tan、log等运算符。如,2sin(x)可以变更为2*sin(x)。

可以理解的是,本实施例不限于上述乘号添加判断方式,还可以采用其他乘号添加判断方式判断是否需要添加乘号,在此不再一一赘述。

另外,如果输入函数是由字符串构成的表达式,则输入函数中存在“=”时,可以进行报错。

在进行数值分割时,需要判断字符是不是数,是不是“.”,对于“1..1”的错误输入,在解析报错,可以不在这里处理。

如果需要处理可以判断当前是不是“.”,解析前面是否存在“.”,如果存在,则报错。

算法:

遍历字符串

当前位置是否是数值

如果当前是数值

添加当前到临时变量

如果当前是“.”

判断之前是否存在“.”

如果之前存在“.”,报错

如果之前不存在“.”,

添加当前到临时变量。

设置存在“.”

遇到其他字符,退出循环

记录临时变量到字符串分割

上述预处理方式中,可以仅包括其中一种预处理方式,也可以同时包括至少两种预处理方式。本实施例所指预处理方式不限于上述预处理方式,还可以包括其他有助于字符串分割或报错判断的预处理方式,在此不一一列举。

在进行字符串分割后,可以调用读取策略对分割获得的字符串进行解析,获得所述输入函数的组成结构。在一个可选的实现方式中,所述读取策略可以包括:

从左到右依次读取分割获得的字符串;

若当前读取的字符串为指定数,将所述指定数作为当前层预定义函数;

若当前读取的字符串为运算符,基于运算符确定需要向右读取的字符串,并将所读取的字符串以及所述运算符确定为当前层预定义函数,基于所读取的字符串确定下一层预定义函数;

若当前读取的字符串为左括号,则调用所述读取策略从左到右依次读取括号内的字符串,直到读取到右括号,基于括号内的字符串确定下一层预定义函数。

其中,指定数可以包括数值、自变量和数学常数。在进行字符串分割后,每个指定数为一个独立的字符串。如果当前所读取的字符串为数值,可以将数值作为当前层预定义函数,如果当前所读取的字符串为自变量,可以将自变量作为当前层预定义函数,如果当前所读取的字符串为数学常数,可以将数学常数作为当前层预定义函数。

运算符可以包括单目运算符和双目运算符。单目运算符可以是运算所需运算对象为一个的运算符,又叫一元运算符。例如,正弦运算符【sin】、余弦运算符【cos】、对数运算符【log】等。双目运算符可以是运算所需运算对象为两个的运算符,例如+,-,*,/,^等。

对于双目运算符而言,往往需要运算符左边的字符串和右边的字符串进行运算。而在确定函数组成结构时,可以暂不考虑运算符为双目运算符或单目运算符,而直接根据运算符确定需要向右读取的字符串,并将运算符和所读取的字符串作为当前层预定义函数。而当前层预定义函数又可以解析为由下一层预定义函数基于运算符或括号构成,因此,可以基于所读取的字符串确定下一层预定义函数。

在一个例子中,如果运算符后的字符为指定数,则将指定数确定为运算符需要向右读取的字符串。进一步的,可以将指定数作为下一层预定义函数。

在另一个例子中,如果运算符后的字符为左括号,则将左括号、以及与左括号对应的右括号、以及括号内的所有字符串确定为运算符需要向右读取的字符串。

具体的,在读取到左括号时可以进入递归,调用所述读取策略从左到右依次读取括号内的字符串,直到读取到右括号,基于括号内的字符串确定下一层预定义函数,结束递归。

针对括号内的字符串仍采用读取策略确定预定义函数。例如,针对括号内字符串,若当前读取的字符串为指定数,将所述指定数作为括号所属层的当前层预定义函数;若当前读取的字符串为运算符,基于运算符确定需要向右读取的字符串,并将所读取的字符串以及所述运算符确定为括号所属层的当前层预定义函数,基于所读取的字符串确定括号所属层的下一层预定义函数,以此类推,直到最后解析获得的预定义函数为指定数。

可见,在遇到非指定数的预定义函数时,会递归解析,直到最底层预定义函数为指定数。

例如,函数解析可以将输入函数分为指定数的当前层预定义函数和非指定数的当前层预定义函数,非指定数的当前层预定义函数又可以被解析为由下一层预定义函数基于运算符或括号构成。当前层预定义函数可以作为输入函数的子函数,下一层预定义函数可以作为当前层预定义函数的子函数,因此函数可以看作由其子函数构成,非指定数的子函数又可以看作由其子函数构成。所以输入函数可以解析为递归的函数。根据上述的定义,可以得到,算法只需要写出一个解析数值和解析函数两个方法就可以做到从字符串分割中解析为函数。

解析函数的算法是先判断当前的字符串分割的值是否是属于函数。如果找到一个函数分割属于函数,那么递归函数解析。函数解析可以创建一张表,用于判断当前的函数分割是否为函数。函数判断表中可以包括两个方法,一个方法是判断条件,通过判断条件可以判断当前字符串分割获得的字符串是否是函数,第二个方法是使用函数分割进行函数创建。函数的条件往往通过判断字符即可,基本的运算符有“+”、“-”、“*”、,函数创建需要区分双目运算符和单目运算符。其中双目运算符包括两个参数,单目运算符包括一个参数。双目运算符必须定义两个参数如何获得,基本双目运算符的参数获得是获得左边的运算对象和右边的运算对象。

以算法的形式进行介绍:

读取函数:

新建函数f。

依次读取字符串分割获得的字符串。

如果读取到是括号,调用读取函数获得函数f1添加到f。

f1=读取函数(字符串分割获得的字符串);

f.subexpression.add(f1);

如果读取到是数值,那么添加数值到f。

如果读取到运算符,那么创建函数f1,判断函数f1需要向后读取多少个字符串,向后读取需要的字符串。

f1=创建函数(函数);//读到sin就创建sin,读到何种运算符就创建该种运算符

for0:f1需要函数;

f1.add(读取函数);

f.subexpression.add(f1);

如果读取到自变量,新建自变量,放到f;

如果读取到数学常数,新建数学常数,放到f;

如果读到右括号),或逗号,函数结束

如果读到其他,不在上面可以进行判断的情况,可以判定为错误,算法结束,提示用户输入错误。

通过上述解析过程,可以获得输入函数的组成结构。

在实际应用中,有些运算符优先级比较高,可以看到最高的是^,然后是*和/,则在获得组成结构后,还可以对输入函数中运算符进行优先级处理。例如,所述直到解析获得的预定义函数为指定数后,还包括:

判断所述输入函数中是否存在指定运算符,所述指定运算符包括乘号、除号和次方运算符;

若存在指定运算符,则按指定运算符的优先级将优先级高的指定运算符以及其所需的运算对象构成的函数作为相邻运算符所在层预定义函数的下一层预定义函数。

其中,乘号和除号的优先级相同,且高于加号、减号的优先级,次方运算符的优先级最高,高于乘号和除号。若存在指定运算符,则按指定运算符的优先级将优先级高的指定运算符以及其所需的运算对象构成的函数作为相邻运算符所在层预定义函数的下一层预定义函数,相当于在优先级高的指定运算符以及其所需的运算对象构成的函数上增加括号,以明示其优先级。

具体的,可以判断组成结构中是否包含运算高的函数,如果包含,且是双目运算符,则需要从之前的函数中拿出,放到优先高的子函数。假如1*2^2那么通过字符串分割和函数解析,可以获得三个函数1,*2,^2。其中*2有一个子函数2。

此时,可以发现存在优先级高的^,因此提取左边函数,如果左边是运算符,那么拆开他获得子函数2,把他添加到一个新的函数,然后添加^到函数,这个函数就是2^2。把该函数2^2放在*子函数,获得*(2^2)这样获得优先级。优先级处理之后,就可以返回一个函数,这个函数可以通过输入x获得输出结果,如果一个表达式没有包括x,那么无论输入什么都不会影响结果。

在获得组成结构后,可以基于所述组成结构执行输入函数中的运算符。其中,可以根据运算符所属单目运算符或双目运算符,确定运算符的运算对象。若运算符的运算对象为非指定数的预定义函数,则根据所述组成结构计算该预定义函数的值,并根据值和运算符获得运算结果;若运算符的预算对象为指定数的预定义函数,则直接根据指定数和运算符获得运算结果;执行完所有运算符后获得所述输入函数中输入值对应的函数值。

以图2所示的输入函数为例进行示例说明。

开始计算函数,需要计算出函数的所有函数。

计算函数1,得到1,放在左边结果。

计算函数2,需要计算函数2.1,得到2。于是计算函数2,需要左边结果和函数2.1结果,得到3,更新左边结果。

计算函数3,需要传入左边结果和函数3.1。开始计算函数3.1,计算函数3.1需要先计算函数3.1.1,而计算函数3.1.1,需要计算函数3.1.1.1和函数3.1.1.2。

计算函数3.1.1.1得到x(x为输入值)。计算函数3.1.1.2需要传入左边结果,传入x,计算函数3.1.1得到函数(x+1)。于是可以计算函数3.1得到sin(x+1)。计算函数3,得到3+sin(x+1)

可以看到,进入函数运算时,需要一个变量,左边结果。如果一个函数里有函数,那么递归进入函数运算。进入函数运算需要判断运算符是否是双目运算符,如果是双目运算符,需要拿左边结果,并且每次运算完更新左边结果。

但是这是双目运算没有优先级,所以在上诉步骤之前,要加上优先级判断。由数学的定律,优先级等于在高优先级的运算添加括号。可以看到1+2*3=1+(2*3),由上述上面定义,括号直接是子函数,所以可以把优先级转换为求子函数创建的问题。只需要递归判断当前的运算符是否比他邻近的运算符优先级高,如果高的话,获得邻近函数的子函数与这个函数组成子函数放在邻近函数的子函数中。对于单目运算符,不进行优先级替换。

可见,需要增加一种运算符时,只需要增加该运算符的计算方法,并指定该运算符的优先级即可,无需重新设计方案或修改整个算法,从而提高方案的可扩展性。

在存在自变量时,可以不断生成输入值,并基于组成结构获得函数值,进而利用由所述输入值和所述函数值构成的点坐标绘制所述输入函数对应的函数图像。由于输入值和函数值可以构成点坐标,因此可以将点坐标作为绘制点(采样点)进行绘制,获得输入函数对应的函数图像。

在实际应用中,往往由于采样点间的距离可能存在严重的连线问题,因此,本实施例采用多线段逼近曲线的方式,解决连线问题。在一个可选的实现方式中,所述利用由所述输入值和所述函数值构成的点坐标绘制所述输入函数对应的函数图像,包括:

采用预设绘制策略对相邻点构成的线段进行绘制和判断,所有点绘制和判断完成后,获得所述输入函数对应的函数图像;所述点基于输入值和函数值构成的点坐标获得;

所述预设绘制策略包括:

绘制由相邻点的第一点和第二点构成的线段;

取所述线段的中点,获得中点坐标;

将中点坐标中的横坐标作为输入函数的输入值,获得输入值对应的函数值;

比较由输入值和函数值构成的目标点与中点的距离;

若所述距离小于指定阈值,则进行下一线段的绘制和判断;

若所述距离大于或等于指定阈值,则删除所述线段,并利用所述预设绘制策略对由第一点和目标点构成的线段进行绘制和判断、以及利用所述预设绘制策略对由目标点和第二点构成的线段进行绘制和判断。

例如,可以设定函数采样点的最小间隔、最大间隔和指定阈值。以y=0,x至左向右计算边界的线段为初始拟合线段,取拟合线段的若干等分点,比较各个等分点,同对应函数点在y方向的距离是否小于指定阈值。若全部点符合,&&等分间隔小于最大间隔,或者,若等分间隔小于最小间隔,则认为线段可以拟合曲线,否则,以各个等分点的对应函数点,构建多线段拟合曲线。各个分线段重复执行上述步骤,形成递归,最终绘制获得函数图像。

可见,可以实现自适应配置采样点间隔,保证实现函数特征,同时减少非必要采样点,提升效率。

以上实施方式中的各种技术特征可以任意进行组合,只要特征之间的组合不存在冲突或矛盾,但是限于篇幅,未进行一一描述,因此上述实施方式中的各种技术特征的任意进行组合也属于本说明书公开的范围。

与前述函数图像绘制方法的实施例相对应,本发明还提供了函数图像绘制装置及其所应用的电子设备、以及计算机存储介质的实施例。

如图4所示,图4是本发明根据一示例性实施例示出的一种函数图像绘制装置的框图,所述装置包括:

函数获取模块410,用于获得输入函数。

结构获得模块420,用于将所述输入函数进行解析,获得所述输入函数的组成结构,其中,所述组成结构中,所述输入函数由至少一个当前层预定义函数构成,当前层预定义函数为指定数或非指定数,非指定数的当前层预定义函数被解析为由下一层预定义函数基于运算符或括号构成,直到底层预定义函数为指定数,所述指定数包括数值、自变量和数学常数。

函数运算模块430,用于基于所述组成结构执行输入函数中的运算符,其中,若运算符的运算对象为非指定数的预定义函数,则根据所述组成结构计算该预定义函数的值,并根据值和运算符获得运算结果,执行完所有运算符后获得所述输入函数中输入值对应的函数值。

图像绘制模块440,用于利用由所述输入值和所述函数值构成的点坐标绘制所述输入函数对应的函数图像。

在一个可选的实现方式中,所述结构获得模块用于:

将所述输入函数按预设分类进行字符串分割,所述预设分类包括指定数类和运算符类;

调用读取策略对分割获得的字符串进行解析,获得所述输入函数的组成结构,所述读取策略包括:

从左到右依次读取分割获得的字符串;

若当前读取的字符串为指定数,将所述指定数作为当前层预定义函数;

若当前读取的字符串为运算符,基于运算符确定需要向右读取的字符串,并将所读取的字符串以及所述运算符确定为当前层预定义函数,基于所读取的字符串确定下一层预定义函数;

若当前读取的字符串为左括号,则调用所述读取策略从左到右依次读取括号内的字符串,直到读取到右括号,基于括号内的字符串确定下一层预定义函数。

在一个可选的实现方式中,所述装置还包括预处理模块,用于:将所述输入函数按预设分类进行字符串分割之前,对所述输入函数进行预处理;

所述对所述输入函数进行预处理,包括以下一种或多种处理:

判断所述输入函数中括号是否成对出现,若括号没有成对出现,则报错;

判断所述输入函数中是否存在不合法字符,若存在不合法字符,则报错;

判断所述输入函数中是否存在相邻的运算符,若存在相邻的加号和减号,则删除加号;若存在相邻的至少两个加号,则保留其中一个加号;若存在相邻的至少两个减号,则当减号个数为基数时,则保留其中一个减号,当减号个数为偶数时,则将该相邻减号替换为一个加号;

判断所述输入函数中是否存在空格,若存在空格,则删除空格;

判断所述输入函数中是否存在省略的乘号,若存在,则在省略乘号的位置处添加乘号;

将所述输入函数中的字母统一变更为大写字母或小写字母。

在一个可选的实现方式中,所述装置还包括优先级处理模块,用于:

判断所述输入函数中是否存在指定运算符,所述指定运算符包括乘号、除号和次方运算符;

若存在指定运算符,则按指定运算符的优先级将优先级高的指定运算符以及其所需的运算对象构成的函数作为相邻运算符所在层预定义函数的下一层预定义函数。

在一个可选的实现方式中,所述图像绘制模块用于:

采用预设绘制策略对相邻点构成的线段进行绘制和判断,所有点绘制和判断完成后,获得所述输入函数对应的函数图像;所述点基于输入值和函数值构成的点坐标获得;

所述预设绘制策略包括:

绘制由相邻点的第一点和第二点构成的线段;

取所述线段的中点,获得中点坐标;

将中点坐标中的横坐标作为输入函数的输入值,获得输入值对应的函数值;

比较由输入值和函数值构成的目标点与中点的距离;

若所述距离小于指定阈值,则进行下一线段的绘制和判断;

若所述距离大于或等于指定阈值,则删除所述线段,并利用所述预设绘制策略对由第一点和目标点构成的线段进行绘制和判断、以及利用所述预设绘制策略对由目标点和第二点构成的线段进行绘制和判断。

相应的,本发明还提供一种电子设备,所述设备包括有处理器;用于存储处理器可执行指令的存储器;其中,所述处理器被配置为:

获得输入函数;

将所述输入函数进行解析,获得所述输入函数的组成结构,其中,所述组成结构中,所述输入函数由至少一个当前层预定义函数构成,当前层预定义函数为指定数或非指定数,非指定数的当前层预定义函数被解析为由下一层预定义函数基于运算符或括号构成,直到底层预定义函数为指定数,所述指定数包括数值、自变量和数学常数;

基于所述组成结构执行输入函数中的运算符,其中,若运算符的运算对象为非指定数的预定义函数,则根据所述组成结构计算该预定义函数的值,并根据值和运算符获得运算结果,执行完所有运算符后获得所述输入函数中输入值对应的函数值;

利用由所述输入值和所述函数值构成的点坐标绘制所述输入函数对应的函数图像。

相应的,本发明实施例一种计算机存储介质,所述存储介质中存储有程序指令,所述程序指令包括:

获得输入函数;

将所述输入函数进行解析,获得所述输入函数的组成结构,其中,所述组成结构中,所述输入函数由至少一个当前层预定义函数构成,当前层预定义函数为指定数或非指定数的当前层预定义函数,非指定数的当前层预定义函数被解析为由下一层预定义函数基于运算符或括号构成,直到底层预定义函数为指定数,所述指定数包括数值、自变量和数学常数;

基于所述组成结构执行输入函数中的运算符,其中,若运算符的运算对象为非指定数的预定义函数,则根据所述组成结构计算该预定义函数的值,并根据值和运算符获得运算结果,执行完所有运算符后获得所述输入函数中输入值对应的函数值;

利用由所述输入值和所述函数值构成的点坐标绘制所述输入函数对应的函数图像。

本发明可采用在一个或多个其中包含有程序代码的存储介质(包括但不限于磁盘存储器、cd-rom、光学存储器等)上实施的计算机程序产品的形式。计算机可用存储介质包括永久性和非永久性、可移动和非可移动媒体,可以由任何方法或技术来实现信息存储。信息可以是计算机可读指令、数据结构、程序的模块或其他数据。计算机的存储介质的例子包括但不限于:相变内存(pram)、静态随机存取存储器(sram)、动态随机存取存储器(dram)、其他类型的随机存取存储器(ram)、只读存储器(rom)、电可擦除可编程只读存储器(eeprom)、快闪记忆体或其他内存技术、只读光盘只读存储器(cd-rom)、数字多功能光盘(dvd)或其他光学存储、磁盒式磁带,磁带磁磁盘存储或其他磁性存储设备或任何其他非传输介质,可用于存储可以被计算设备访问的信息。

上述装置中各个模块的功能和作用的实现过程具体详情见上述方法中对应步骤的实现过程,在此不再赘述。

对于装置实施例而言,由于其基本对应于方法实施例,所以相关之处参见方法实施例的部分说明即可。以上所描述的装置实施例仅仅是示意性的,其中所述作为分离部件说明的模块可以是或者也可以不是物理上分开的,作为模块显示的部件可以是或者也可以不是物理模块,即可以位于一个地方,或者也可以分布到多个网络模块上。可以根据实际的需要选择其中的部分或者全部模块来实现本发明方案的目的。本领域普通技术人员在不付出创造性劳动的情况下,即可以理解并实施。

本发明函数图像绘制装置的实施例可以应用在电子设备上。装置实施例可以通过软件实现,也可以通过硬件或者软硬件结合的方式实现。以软件实现为例,作为一个逻辑意义上的装置,是通过其所在电子设备的处理器将非易失性存储器中对应的计算机程序指令读取到内存中运行形成的。从硬件层面而言,如图5所示,为本发明函数图像绘制装置532所在电子设备的一种硬件结构图,除了图5所示的处理器510、内存530、网络接口520、以及非易失性存储器540之外,实施例中装置532所在的电子设备通常根据该电子设备的实际功能,还可以包括其他硬件,对此不再赘述。

本领域技术人员在考虑说明书及实践这里公开的发明后,将容易想到本发明的其它实施方案。本发明旨在涵盖本发明的任何变型、用途或者适应性变化,这些变型、用途或者适应性变化遵循本发明的一般性原理并包括本发明未公开的本技术领域中的公知常识或惯用技术手段。说明书和实施例仅被视为示例性的,本发明的真正范围和精神由下面的权利要求指出。

应当理解的是,本发明并不局限于上面已经描述并在附图中示出的精确结构,并且可以在不脱离其范围进行各种修改和改变。本发明的范围仅由所附的权利要求来限制。

以上所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内,所做的任何修改、等同替换、改进等,均应包含在本发明保护的范围之内。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1