一元、二元函数图像绘制

简介:

目录

 

概述

本篇博客主要是在上一篇《每个人都该懂点函数式编程》的基础上,进一步说明“函数”在函数式编程中的重要作用。强调了函数和普通类型一样,可以赋值、存储、传参以及作为另外函数的返回值。

本文附带了一个Demo,该Demo可以将任意字符串函数表达式解析之后生成对应的函数(一元、二元以及三元),如果你输入的是一元或者二元函数表达式,则可以绘制出相应的函数图像。一元函数图像为平面曲线,二元函数图像为立体曲面。看下图:

函数表达式中只识别X、Y、Z三个自变量。

Github源码下载

 

字符串表达式解析

字符串解析是重点。

怎样去识别一串字符串函数表达式呢?如x^2+sin(x)*cos(y)。之后怎样去计算函数值呢?其实原理很简单,由于每个函数表达式中包含的有效符号是有限的,如X、Y、Z、+、-、*、/以及一些函数诸如log、sin、cos等等,只要我们将这些有效符号均识别筛选出来之后,再根据这些符号的优先级别生成一个函数语法树即可。

如上图所示,使用一个“树结构”去存储最终的语法树。最后带入X、Y(二元)求得函数值。

表达式解析这块难点是语法树的构建和最终求值。语法树的构建有点复杂,大家可以参见源码;最终求值的原理是,判断当前符号(节点)是单目运算符号(如cos、sin、负号等)还是双目运算符号(如+ - * /等),如果是单目运算比如cos函数,则先计算子节点(只有一个子节点)的值,然后将得到的值进行cos运算(Math.Cos(子节点的值));相反,如果是双目运算符比如+符号,那么先计算左子节点和右子节点的值,最后将两个值进行+操作(左子节点的值+右子节点的值),依次递归计算得到最终的函数值。

 

图像绘制

图像绘制这块就比较简单了。根据前一步得到的语法树,我们可以创建出对应的一元函数、二元函数以及三元函数(委托的形式)。事先定义的委托结构如下:

    /// <summary>
    /// 一元函数
    /// </summary>
    /// <param name="x"></param>
    /// <returns></returns>
    public delegate double UnaryFunction(double x);
    /// <summary>
    /// 二元函数
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <returns></returns>
    public delegate double BinaryFunction(double x,double y);
    /// <summary>
    /// 三元函数
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <param name="z"></param>
    /// <returns></returns>
    public delegate double MultiFunction(double x,double y,double z);

很简单就可以看出,一元函数接收一个参数,返回一个值;二元函数接收两个参数,返回一个值;三元函数接收三个参数,返回一个值。生成委托的过程如下:

   (UnaryFunction)((double x) => { return root.GetValue(x, 0, 0); });
   (BinaryFunction)((double x, double y) => { return root.GetValue(x, y, 0); });
   (MultiFunction)((double x, double y, double z) => { return root.GetValue(x, y, z); });

最终给出对应的x、y、z调用委托,即可得到函数值。

一元函数绘制

随便对X取一个区间(如[-10,10]),以0.1为间距,计算每个X对应的Y值(函数值)。最终将这些点连接起来,出来的就是对应的一元函数图像。

二元函数绘制

相似的,随便对X、Y取一个区间(如X取[-10,10],Y取[-10,10]),X、Y均以0.1为间距,计算每个(X、Y)对应的Z值(函数值),最后将这些三维点绘制成曲面。

 

函数作为属性赋值

经过前几步得到了函数(委托对象),我们直接将委托对象作为属性赋给图像绘制控件,绘图控件更新界面。

   //一元
   if (textBox1.Text.ToLower().Contains('x') && !textBox1.Text.ToLower().Contains('y') && !textBox1.Text.ToLower().Contains('z'))
   {
       UnaryFunction func = (new SyntaxManager().ParseUnaryFunction(textBox1.Text));
       unaryFunctionDrawingBoard1.Function = func;
       tabControl1.SelectedIndex = 0;
   }
   //二元
   else if (textBox1.Text.ToLower().Contains('x') && textBox1.Text.ToLower().Contains('y') && !textBox1.Text.ToLower().Contains('z'))
   {
       BinaryFunction func = (new SyntaxManager().ParseBinaryFunction(textBox1.Text));
       binaryFunctionDrawingBoard1.BinaryFunction = func;
       tabControl1.SelectedIndex = 1;
   }
   //三元
   else
   {
        MultiFunction func = (new SyntaxManager().ParseMultiFunction(textBox1.Text));
        MessageBox.Show("三元函数图像无法绘制!");
   }

如上代码,函数作为属性赋值的示例。

 

参考及说明

1.Demo中有关3D图形绘制参考了网上的一个OpenTK的demo:http://download.csdn.net/detail/dragonflies/3418135#comment

2.函数图像在线生成(为了验证demo生成的图像是否正确)

3.注意 函数绘制时没有做任何区间验证,比如logX中的X不能为负,否则无效(绘制时异常)。这些需要自己注意。

 

作者:周见智 
出处:http://www.cnblogs.com/xiaozhi_5638/ 
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

分类:  非主流玩一玩

本文转自周见智博客博客园博客,原文链接:http://www.cnblogs.com/xiaozhi_5638/p/4794478.html,如需转载请自行联系原作者
目录
相关文章
|
机器学习/深度学习 人工智能 文字识别
探索AI技术对古彝文保护与研究应用
探索AI技术对古彝文保护与研究应用
864 2
|
前端开发 JavaScript API
基于Vue+ELement实现增删改查案例与表单验证
基于Vue+ELement实现增删改查案例与表单验证
1484 0
|
存储 JavaScript 对象存储
oss与cdn的区别与联系
oss与cdn的区别与联系
906 0
|
5月前
|
人工智能 安全 关系型数据库
Dataphin V5.4版本发布:拥有「最强大脑」的数据治理平台,究竟智能在哪儿?
Dataphin V5.4 正式发布,升级集成、治理、安全与运维能力。支持API/FTP增强、多源数据接入、智能质量分析、外部血缘注册、增删改API、行级权限申请及资源监控,助力企业高效构建标准化数据体系,释放数据价值。
222 0
|
Kubernetes Java Linux
Linux|操作系统|Error: Could not create the Java Virtual Machine 报错的解决思路
Linux|操作系统|Error: Could not create the Java Virtual Machine 报错的解决思路
4275 0
|
3月前
|
传感器 编解码 算法
如何挑选合适的数字式相位差测量仪、数字式相位测量仪、相位测试仪厂家
SYN5607型相位计是西安同步自主研发的高精度数字相位测量仪,广泛应用于电力、通信与工业自动化领域。相位差反映同频信号的时间关系,微小偏差可能引发功率损耗、通信误码或设备故障。该仪器采用过零鉴相法,支持0.5Hz-5MHz宽频测量,精度高达±0.02°,时间分辨率达1ns,并可扩展至2.7GHz。具备多波形兼容、高频模块选配等优势,适用于电网监测、5G通信测试、电机控制及科研计量,助力实现精准同步与高效系统运行。(238字)
|
SQL 关系型数据库 MySQL
数据库导入SQL文件:全面解析与操作指南
在数据库管理中,将SQL文件导入数据库是一个常见且重要的操作。无论是迁移数据、恢复备份,还是测试和开发环境搭建,掌握如何正确导入SQL文件都至关重要。本文将详细介绍数据库导入SQL文件的全过程,包括准备工作、操作步骤以及常见问题解决方案,旨在为数据库管理员和开发者提供全面的操作指南。一、准备工作在导
2179 0
|
数据可视化 搜索推荐 Shell
Python与Plotly:B站每周必看榜单的可视化解决方案
Python与Plotly:B站每周必看榜单的可视化解决方案
|
运维 负载均衡 算法
Nacos必知必会:这些知识点你一定要掌握!
Nacos必知必会:这些知识点你一定要掌握!
1937 0
|
数据可视化 数据处理 开发者
构建高效的数据流图:Python与PyGraphviz的实践
【9月更文挑战第13天】在本文中,我们将探索如何利用Python和PyGraphviz库来创建和操作数据流图。我们将通过一个具体示例,展示如何从零开始构建一张数据流图,并讨论如何优化图表以提高可读性。文章旨在为初学者提供一个清晰的入门指南,同时为有经验的开发者提供一些高级技巧。