画二元函数图像_二元函数怎么画图

画二元函数图像_二元函数怎么画图目录概述字符串表达式解析图像绘制函数作为属性赋值参考以及说明概述本篇博客主要是在上一篇《每个人都该懂点函数式编程》的基础上,进一步说明“函数”在函数式编程中的重要作用。强调了函数和普通类型一样,可以赋

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

目录

 

概述

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

本文附带了一个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不能为负,否则无效(绘制时异常)。这些需要自己注意。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/166555.html原文链接:https://javaforall.net

(0)
上一篇 2022年8月6日 上午10:36
下一篇 2022年8月6日 上午10:36


相关推荐

  • Python 求圆的面积[通俗易懂]

    Python 求圆的面积[通俗易懂]r=int(input(‘输入半径值:’))area=3.1415*r*rprint(area)#保留小数点后两位print(‘{:.2f}’.format(area))“`

    2025年8月19日
    4
  • DHCP协议解析

    DHCP协议解析DHCP(DynamicHostConfigurationProtocol,动态主机配置协议)是IETF为实现IP的自动配置而设计的协议,它可以为客户机自动分配IP地址、子网掩码以及缺省网关、DNS服务器的IP地址等TCP/IP参数。了解DHCP工作过程可以帮助我们排除有关DHCP服务遇到的问题。DHCP协议是基于UDP层之上的应用,本文结合抓报所得数据分析DHCP协议实现原理一、

    2022年5月23日
    51
  • c语言调用循环内部函数,通达信绘图函数调用,通达信调用内部数据[通俗易懂]

    c语言调用循环内部函数,通达信绘图函数调用,通达信调用内部数据[通俗易懂]内容导航:Q1:通达信函数大全使用说明内容来自用户:艳我爱你you软件简介:通达信全部函数及其用法(2011年最新版)(一)行情函数1)HIGH(H)最高价返回该周期最高价.2)LOW(L)最低价返回该周期最低价.3)CLOSE(C)收盘价返回该周期收盘价.4)VOL(V)成交量(手)返回该周期成交量.5)OPEN(O)开盘价返回该周期开…

    2025年6月20日
    5
  • Navicat Premium相关注册码「建议收藏」

    Navicat Premium相关注册码「建议收藏」–NavicatforSQLServerV10.0.10NAVD-3CG2-6KRN-IEPMNAVL-NIGY-6MYY-XWQENAVI-C3UU-AAGI-57FW–NavicatPremium注册码NAVJ-E6YF-JULL-KKIGNAVE-BOCL-CE3X-TAGYNAVC-KAIA-NU5I-SPOXNAVL-FE27-KNTQ-YJXCNAVK-LXKO-3XHL…

    2022年10月13日
    4
  • JVM相关问题整理

    备注:针对基本问题做一些基本的总结,不是详细解答!1.运行时数据区域(内存模型)(必考)2.垃圾回收机制(必考)3.垃圾回收算法(必考)4.MinorGC和FullGC触发条件5.GC中Stoptheworld(STW)6.各垃圾回收器的特点及区别,怎么做选择?7.双亲委派模型8.JDBC和双亲委派模型关系9.JVM锁优化和锁膨胀过程10.JVM中G…

    2022年4月6日
    36
  • android registerreceiver() 参数,android – 如何使用registerReceiver方法?

    android registerreceiver() 参数,android – 如何使用registerReceiver方法?我想使用动态注册的BroadcastReceiver有一个Activity的引用,所以它可以修改其UI。我使用Context.registerReceiver()方法,但接收器的onReceive()方法从未调用。这里是显示问题的示例代码:packagecom.example;importandroid.app.Activity;importandroid.app.IntentService…

    2025年10月31日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号