尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
使用 JavaFX + Reactor 绘制函数图像并数值求解交点 —— 原理与实现
使用 JavaFX Reactor 绘制函数图像并数值求解交点 —— 原理与实现在数值计算与可视化中我们常常需要绘制函数曲线并标注其交点。本文将以一个完整的 Java 程序为例深入剖析如何利用Reactor生成数据点、JavaFX绘制曲线并通过纯数值方法符号检测 二分法求解交点最终在图上以空心圆圈和坐标标签的形式清晰显示。代码全程不依赖任何数学求导公式完全基于离散点采样与迭代逼近具有通用性强、易于扩展的特点。一、程序概览我们定义两个函数( f1(x) 3x^2 - 1 )二次函数( f2(x) 2x - 1 )一次函数目标是绘制它们在区间 ([-5, 5]) 上的图像并求出所有交点坐标在图上用空心圆标注。二、数据生成Reactor 的Flux流2.1 为何使用 ReactorReactor 提供了一套响应式编程 API其Flux可以方便地生成大量离散数据点并以声明式的方式进行处理。与传统 for 循环相比Flux更易于组合、并行处理和链式操作。2.2 代码解析doublestep0.01;doublestartX-5.0;doubleendX5.0;intcount(int)((endX-startX)/step)1;Flux.range(0,count).map(i-startXi*step).doOnNext(x-{series1.getData().add(newXYChart.Data(x,f1(x)));series2.getData().add(newXYChart.Data(x,f2(x)));}).blockLast();Flux.range(0, count)生成一个整数序列 0 到 count-1。map(i - startX i * step)将每个索引映射为对应的 ( x ) 值从而得到均匀分布的离散点。doOnNext是副作用操作在每次发出 ( x ) 时计算两个函数值并添加到 JavaFX 的Series数据列表中。blockLast()阻塞当前线程直到所有数据生成完毕。由于数据量不大约 1000 点该操作对 UI 线程影响很小。这样我们便得到了绘制曲线所需的所有点。三、绘图JavaFX 的LineChart3.1 坐标轴设置NumberAxisxAxisnewNumberAxis();xAxis.setLowerBound(-5);xAxis.setUpperBound(5);xAxis.setAutoRanging(false);固定 x 轴范围确保定义域完整显示。y 轴则自动适应数据范围。3.2 创建图表与系列LineChartNumber,NumberchartnewLineChart(xAxis,yAxis);XYChart.SeriesNumber,Numberseries1newXYChart.Series();series1.setName(f1(x) 3x² - 1);LineChart会按照数据点顺序连接成折线由于步长足够小0.01曲线将非常平滑。setCreateSymbols(false)禁用默认数据点符号避免干扰。3.3 添加数据在doOnNext中我们直接将计算出的数据点加入series的getData().add()该方法会在 JavaFX 应用程序线程中更新但blockLast()会阻塞 UI 线程直到所有点添加完毕这个过程只持续几十毫秒用户无感知。四、数值求解交点4.1 原理两个连续函数的交点满足 ( f_1(x) f_2(x) )等价于差值函数 ( h(x) f_1(x) - f_2(x) ) 的零点。若 ( h(x) ) 在某区间两端异号则根据介值定理该区间内必存在至少一个根。4.2 实现步骤离散采样在定义域内以步长step采样计算每个点的 ( h(x) )。符号检测遍历相邻点若h1 * h2 0则说明该区间内存在根。二分法精化对每个含根区间使用二分法Bisection Method迭代求根直到区间宽度小于给定精度1e-10。处理端点若某点 ( h(x) ) 恰好为零或绝对值极小直接视为交点。privateListdouble[]findIntersections(doublestep,doublestartX,doubleendX){Listdouble[]resultnewArrayList();intcount(int)((endX-startX)/step)1;double[]xValsnewdouble[count];double[]hValsnewdouble[count];for(inti0;icount;i){doublexstartXi*step;xVals[i]x;hVals[i]f1(x)-f2(x);}for(inti0;icount-1;i){if(hVals[i]*hVals[i1]0){doublerootbisect(xVals[i],xVals[i1]);doubleyf1(root);result.add(newdouble[]{root,y});}if(Math.abs(hVals[i])1e-12){doubleyf1(xVals[i]);result.add(newdouble[]{xVals[i],y});}}// 检查最后一点if(Math.abs(hVals[count-1])1e-12){doubleyf1(xVals[count-1]);result.add(newdouble[]{xVals[count-1],y});}returnresult;}4.3 二分法细节privatedoublebisect(doublea,doubleb){doubleeps1e-10;doublemid;intmaxIter100;for(inti0;imaxIter;i){mid(ab)/2;doublefaf1(a)-f2(a);doublefmf1(mid)-f2(mid);if(Math.abs(fm)eps)returnmid;if(fa*fm0)bmid;elseamid;}return(ab)/2;}二分法保证收敛且精度可控。对于本例只需几次迭代即可达到1e-10精度。五、交点标注自定义节点5.1 需求使用空心圆圈标记交点位置。在圆圈上方显示坐标标签避免遮挡曲线。5.2 实现为每个交点数据创建一个XYChart.Data并通过setNode设置自定义的StackPane。XYChart.DataNumber,NumberdatanewXYChart.Data(p[0],p[1]);StackPanenodenewStackPane();CirclecirclenewCircle(6);circle.setFill(null);// 空心circle.setStroke(Color.RED);circle.setStrokeWidth(2);LabellabelnewLabel(String.format((%.2f, %.2f),p[0],p[1]));label.setTextFill(Color.BLUE);label.setTranslateY(-20);// 上移node.getChildren().addAll(circle,label);data.setNode(node);5.3 为什么放在最上层先添加曲线系列series1, series2再添加交点系列使得交点绘制在曲线之上避免被覆盖。六、为什么数值解与解析解一致令 ( f_1(x) f_2(x) )[3x^2 - 1 2x - 1 \Rightarrow 3x^2 - 2x 0 \Rightarrow x0 \text{ 或 } x\frac{2}{3}]对应 y 值为 -1 和 1/3。数值解在1e-10精度下完全吻合验证了算法的正确性。这证明了在步长足够小、二分法精度足够高的情况下数值方法能可靠地逼近解析解。七、与之前学习内容的联系Context/ContextView虽未直接用于此程序但理解上下文传递有助于在更复杂的响应式流中传递调试信息。SynchronousSinkFlux.generate曾用于创建无限流而本例使用Flux.range生成有限点集两者都是 Reactor 生成数据的常用方式。Fuseable内部优化对于大量数据点可提升性能但本例数据量不大未显式使用。数值求交延续了之前对数函数导数、三角数流等数值计算的思想体现了响应式流在科学计算中的实用性。八、运行与效果运行程序后窗口显示两条平滑曲线交点处出现红色空心圆圈上方附有蓝色坐标标签清晰无遮挡。控制台无额外输出全部信息可视化。九、总结本文通过一个完整的 Java 程序展示了如何结合Reactor和JavaFX响应式生成大量离散点以绘制平滑曲线。利用数值差分法符号检测 二分法求解函数交点。自定义图表节点实现空心圆圈与标签标注。该方案不依赖解析公式可推广至任意连续函数具有广泛的应用价值。掌握这些技术将为后续的数值分析与可视化开发奠定坚实基础。完整代码publicclassFunctionPlotterextendsApplication{// 定义函数导数 f1(x) 3x² - 1privatedoublef1(doublex){return3*x*x-1;}// 定义函数直线 f2(x) 2x - 1privatedoublef2(doublex){return2*x-1;}Overridepublicvoidstart(StageprimaryStage){// 坐标轴NumberAxisxAxisnewNumberAxis();xAxis.setLabel(x);xAxis.setLowerBound(-5);xAxis.setUpperBound(5);xAxis.setAutoRanging(false);NumberAxisyAxisnewNumberAxis();yAxis.setLabel(y);yAxis.setAutoRanging(true);// 图表LineChartNumber,NumberchartnewLineChart(xAxis,yAxis);chart.setTitle(导数函数与直线交点);chart.setCreateSymbols(false);// 不显示数据点默认符号避免干扰doublestep0.01;doublestartX-5.0;doubleendX5.0;intcount(int)((endX-startX)/step)1;// 系列1f1(x)XYChart.SeriesNumber,Numberseries1newXYChart.Series();series1.setName(f1(x) 3x² - 1);// 系列2f2(x)XYChart.SeriesNumber,Numberseries2newXYChart.Series();series2.setName(f2(x) 2x - 1);// 使用 Reactor 生成数据点Flux.range(0,count).map(i-startXi*step).doOnNext(x-{series1.getData().add(newXYChart.Data(x,f1(x)));series2.getData().add(newXYChart.Data(x,f2(x)));}).blockLast();// ---- 数值求交点 ----Listdouble[]intersectionsfindIntersections(step,startX,endX);// 交点系列自定义节点空心圆圈 坐标标签XYChart.SeriesNumber,NumberintersectionSeriesnewXYChart.Series();intersectionSeries.setName(交点);for(double[]p:intersections){XYChart.DataNumber,NumberdatanewXYChart.Data(p[0],p[1]);// 自定义节点空心圆 标签StackPanenodenewStackPane();CirclecirclenewCircle(6);circle.setFill(null);// 空心circle.setStroke(Color.RED);circle.setStrokeWidth(2);LabellabelnewLabel(String.format((%.2f, %.2f),p[0],p[1]));label.setTextFill(Color.BLUE);label.setStyle(-fx-font-size: 12px; -fx-font-weight: bold;);label.setTranslateY(-20);// 标签上移避免遮挡node.getChildren().addAll(circle,label);data.setNode(node);intersectionSeries.getData().add(data);}// 添加所有系列到图表先添加曲线再添加交点保证交点在最上层chart.getData().addAll(series1,series2,intersectionSeries);// 可选设置交点系列默认样式透明以防默认样式干扰intersectionSeries.getNode().setStyle(-fx-stroke: transparent; -fx-background-color: transparent;);// 显示窗口ScenescenenewScene(chart,800,600);primaryStage.setScene(scene);primaryStage.show();}/** * 数值求解交点差值函数 h(x)f1(x)-f2(x) 的零点 */privateListdouble[]findIntersections(doublestep,doublestartX,doubleendX){Listdouble[]resultnewArrayList();intcount(int)((endX-startX)/step)1;double[]xValsnewdouble[count];double[]hValsnewdouble[count];for(inti0;icount;i){doublexstartXi*step;xVals[i]x;hVals[i]f1(x)-f2(x);}for(inti0;icount-1;i){doubleh1hVals[i];doubleh2hVals[i1];if(h1*h20){doublerootbisect(xVals[i],xVals[i1]);doubleyf1(root);result.add(newdouble[]{root,y});}// 处理恰好为零的点if(Math.abs(h1)1e-12){doubleyf1(xVals[i]);result.add(newdouble[]{xVals[i],y});}}if(Math.abs(hVals[count-1])1e-12){doubleyf1(xVals[count-1]);result.add(newdouble[]{xVals[count-1],y});}returnresult;}/** * 二分法求根精度 1e-10 */privatedoublebisect(doublea,doubleb){doubleeps1e-10;doublemid;intmaxIter100;for(inti0;imaxIter;i){mid(ab)/2;doublefaf1(a)-f2(a);doublefmf1(mid)-f2(mid);if(Math.abs(fm)eps)returnmid;if(fa*fm0)bmid;elseamid;}return(ab)/2;}publicstaticvoidmain(String[]args){launch(args);}}
RELATED

相关推荐

开源正在重塑AI的权力版图——从美国科技巨头的集体转向说起

开源正在重塑AI的权力版图——从美国科技巨头的集体转向说起

2026年7月,硅谷发生了一件耐人寻味的事。 英伟达CEO黄仁勋在X平台上发布了人生第一条推文。推文附上一封公开信,标题是《开放权重与美国在AI领域的领导地位》。签署方包括英伟达、微软、Meta、IBM、Hugging Face、Mistral AI等25家科技公司和机构。此后…

📅 2026/9/9 15:51:52
华尔街正在重新审视AI的价值——从四大云厂财报看AI的“变现分水岭”

华尔街正在重新审视AI的价值——从四大云厂财报看AI的“变现分水岭”

2026年7月底,美国四大云厂商相继交出最新季度的成绩单。数据全线大超市场预期,但资本市场的反应却冰火两重天。微软和亚马逊股价应声大涨,市值合计单日飙升超过3000亿美元。谷歌母公司Alphabet和Meta的股价却在财报发布后双双大跌——尽管它们…

📅 2026/9/9 21:34:32
写了一个全功能的 RocketMQ .NET 客户端:EventHorizon.RocketMQ

写了一个全功能的 RocketMQ .NET 客户端:EventHorizon.RocketMQ

目录 前言功能概览它不是官方客户端的替代品快速接入 先启动本地测试环境gRPC:通过 Proxy 连接 RocketMQ 5Remoting:通过 NameServer 发现 Broker多集群或多实例 发送消息消费消息 gRPC 的消费模型 PushConsumer classic Remoting 的消费模型 PushConsu…

📅 2026/10/7 8:41:34
MORE NEWS

更多资讯

📰

A股三十年现金流季度指标库:字段口径、Stata/Python处理与实证应用

简介:一份面向金融数据研究者的资源文档,内含百度网盘分享链接及提取码,可获取1991—2024年6月沪深北上市公司财务指标现金流分析数据。数据按季度整理,覆盖沪深北证A股主板、中小企业板、创业板、科创板,字段涵盖净利…

📰

加密恶意流量检测机器学习平台:原理、训练与Flask部署实战

简介:基于Python机器学习的加密恶意流量分析与检测平台,是一份面向网络安全、机器学习方向学生及从业者的完整项目资源。针对HTTPS普及背景下加密流量难以识别的问题,项目包含恶意流量检测模型、训练与预测模块、基于Flask的流量监测平台&…

📰

申请评分卡模型实战:从Python数据集到WOE分箱与评分映射

简介:这份资源面向金融风控方向的学习者与数据科学从业者,聚焦用Python实现申请评分卡模型,帮助理解从原始申请数据到信用评分的完整建模链路。包内共14个文件,以pkl序列化中间产物、py建模脚本、csv原始数据集及lr_classweight权…

📰

手写BP神经网络实现Excel回归预测:numpy从0到1完整流程

简介:基于BP神经网络的数据回归预测源码,面向机器学习初学者与需要快速验证回归模型的开发者,使用numpy搭建网络,并用matplotlib完成可视化。资源包共6个文件,内含可运行脚本、两个Excel数据集(训练/测试&a…

📰

WinCC用户归档从建表到脚本读写:点检记录数字化实战

简介:面向工业自动化与SCADA开发者的西门子WinCC用户归档专题案例,聚焦生产数据存储与检索场景,系统讲解动作(Actions)与标准模块之间的协同机制,帮助解决历史数据管理、报表生成与故障排查中的实际难题。压…

📰

一夜之间,俄罗斯科技巨头下场:Yandex 为什么偏偏在现在开源 80B 基座

一夜之间,俄罗斯科技巨头下场:Yandex 为什么偏偏在现在开源 80B 基座 【免费下载链接】AliceAI-Foundation-80B-A3B-Base 项目地址: https://ai.gitcode.com/hf_mirrors/yandex/AliceAI-Foundation-80B-A3B-Base 当开源大模型的天平被 DeepSeek …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬