实验3预测分析法
- 格式:doc
- 大小:150.50 KB
- 文档页数:23
第1篇一、实验背景随着大数据技术的飞速发展,数据分析和预测在各个行业中扮演着越来越重要的角色。
销售预测作为企业制定销售策略、优化资源配置、提升市场竞争力的关键环节,其准确性直接关系到企业的经济效益。
本实验旨在通过构建数据销售预测模型,验证其预测效果,为企业提供科学合理的销售预测方案。
二、实验目的1. 构建数据销售预测模型,分析销售数据与相关因素之间的关系。
2. 评估模型预测准确性,为实际应用提供参考。
3. 探索影响销售的关键因素,为企业制定销售策略提供依据。
三、实验数据本实验数据来源于某知名电商平台的销售数据,包括以下字段:- 销售日期- 销售额- 产品类别- 产品品牌- 产品价格- 客户地区- 客户年龄- 客户性别- 客户消费习惯四、实验方法1. 数据预处理:对原始数据进行清洗、处理,包括缺失值填充、异常值处理、数据标准化等。
2. 特征工程:根据业务需求,选取与销售数据相关的特征,如产品类别、品牌、价格、地区、年龄、性别等。
3. 模型选择:选择合适的预测模型,如线性回归、决策树、随机森林、神经网络等。
4. 模型训练与验证:使用历史销售数据对模型进行训练,并使用交叉验证等方法评估模型性能。
5. 模型优化:根据验证结果,调整模型参数,优化模型性能。
6. 预测与分析:使用优化后的模型对未来的销售数据进行预测,并分析预测结果。
五、实验结果与分析1. 模型选择与训练本实验选取了线性回归、决策树、随机森林、神经网络等模型进行预测。
经过交叉验证,随机森林模型的预测效果最佳,其均方误差(MSE)为0.095,R²值为0.95。
2. 特征重要性分析通过分析特征重要性,发现以下因素对销售数据影响较大:- 产品类别:不同产品类别的销售情况存在显著差异。
- 价格:价格对销售数据的影响较为明显,价格较低的产品销售情况较好。
- 客户地区:不同地区的销售情况存在差异,可能与地区消费习惯、市场竞争等因素有关。
3. 预测结果分析使用优化后的随机森林模型对未来的销售数据进行预测,预测结果如下:- 预测销售额:未来3个月销售额预计为1000万元。
实验数据的处理和分析方法在科学研究中,实验数据的处理和分析是非常重要的一步。
通过合理的数据处理和分析方法,我们可以从海量数据中提取有用的信息,得出科学结论,并为后续的研究工作提供指导。
本文将介绍一些常用的实验数据处理和分析方法。
一、数据的预处理数据的预处理是数据分析的第一步,主要包括数据清洗、数据采样和数据归一化等过程。
1. 数据清洗数据清洗是指对数据中存在的错误、异常值和缺失值进行处理。
在清洗数据时,我们需要识别和删除不合理或错误的数据,修复异常值,并使用插补方法处理缺失值。
2. 数据采样数据采样是从大量数据集中选择一小部分样本进行分析和处理的过程。
常用的数据采样方法包括随机抽样、等距抽样和分层抽样等。
3. 数据归一化数据归一化是将不同量纲的数据统一到相同的尺度上,以便进行比较和分析。
常用的数据归一化方法包括最小-最大归一化和标准化等。
二、数据的描述和统计分析在对实验数据进行分析之前,我们需要对数据进行描述和统计,以了解数据的分布情况和特征。
1. 描述统计分析描述统计分析是通过一些统计指标对数据的基本特征进行描述,如平均数、中位数、方差和标准差等。
这些统计指标可以帮助我们了解数据的集中趋势、离散程度和分布情况。
2. 统计图表分析统计图表分析是通过绘制直方图、饼图、散点图等图表,可视化地展示数据分布和变化趋势。
通过观察统计图表,我们可以更直观地理解数据之间的关系和规律。
三、数据的相关性和回归分析数据的相关性和回归分析能够帮助我们了解变量之间的关系,在一定程度上预测和解释变量的变化。
1. 相关性分析相关性分析是研究变量之间相关程度的一种方法。
通过计算相关系数,如皮尔逊相关系数和斯皮尔曼等级相关系数,我们可以判断变量之间的线性关系和相关强度。
2. 回归分析回归分析是一种建立变量之间函数关系的方法。
通过回归模型,我们可以根据自变量的变化预测因变量的变化。
常用的回归分析方法包括线性回归、多项式回归和逻辑回归等。
初中科学实验结果分析方法总结实验结果分析是科学实验中非常重要的一部分,通过对实验结果的分析,我们可以得出结论,验证实验假设,进一步推断或解释实验现象,为科学研究提供证据和支持。
下面是初中科学实验结果分析方法的总结:1.数据整理:在进行实验结果分析之前,首先要对实验数据进行整理和清理。
确保数据的准确性和完整性,去除可能存在的异常值或错误数据,以保证分析的可靠性和准确性。
2.数据图表化:将实验数据以图表的形式展示出来,有助于直观地观察实验结果的分布和变化规律。
常用的数据图表包括柱状图、折线图、散点图等,通过这些图表可以更清晰地看出数据之间的关系和趋势。
3.平均值计算:计算实验数据的平均值是一种常用的结果分析方法。
通过计算平均值可以对数据的集中程度进行评估,了解数据的总体倾向。
平均值是对数据集中趋势的一个简要描述,可以帮助我们初步判断实验结果的特点和规律。
4.方差分析:方差分析是一种用来检验不同组别之间差异是否显著的统计方法。
对于实验结果有多个组别的情况,可以利用方差分析来比较各组别之间的差异是否有统计学意义,确定是否存在显著差异。
5.相关性分析:在一些涉及多个变量的实验中,我们常常需要通过相关性分析来探究变量之间的关系。
通过计算相关系数可以评估变量之间的线性相关程度,进而判断它们之间是否存在相关性和关联性。
6.对比分析:对比分析是一种比较不同组间或样本间差异的方法。
通过对比分析可以发现不同条件下的差异和变化,从而得出结论,并验证实验假设。
常用的对比分析方法包括比较平均值、比较频数等。
7.数据模型拟合:有时候实验数据并不完全符合预期的理论模型,需要通过数据模型拟合来找到更合适的解释。
通过拟合数据模型可以更好地理解数据的规律和趋势,为实验结果的解释提供更深入的参考。
综上所述,实验结果分析是科学实验中不可或缺的一部分,通过科学合理的方法对实验结果进行准确分析,可以得出准确的结论和科学的解释。
希望以上总结的初中科学实验结果分析方法对您有所帮助。
预测分析程序实验报告题⽬:预测分析法⼀、实验⽬的1、通过实验要学会⽤消除左递归和消除回溯的⽅法来使⽂法满⾜进⾏确定⾃顶向下分析的条件;2、学会⽤C/C++⾼级程序设计语⾔编写⼀个LL(1)分析法程序⼆、实验内容及要求LL(1)预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输⼊符号a做哪种过程的。
对于任何(X,a),总控程序每次都执⾏下述三种可能的动作之⼀:(1)若X = a =‘#’,则宣布分析成功,停⽌分析过程。
(2)若X = a ‘#’,则把X从STACK栈顶弹出,让a指向下⼀个输⼊符号。
(3)若X是⼀个⾮终结符,则查看预测分析表M。
若M[A,a]中存放着关于X的⼀个产⽣式,那么,⾸先把X弹出STACK栈顶,然后,把产⽣式的右部符号串按反序⼀⼀弹出STACK栈(若右部符号为ε,则不推什么东西进STACK栈)。
若M[A,a]中存放着“出错标志”,则调⽤出错诊断程序ERROR。
1、给定⽂法S -> a | b | (T)T -> SH | dH -> ,SH | ε2、该⽂法对应的预测分析表3、编写预测分析程序对句⼦进⾏分析三、试验程序设计说明1、相关函数说明分析栈可以采取许多的存储⽅法来设计,在这⾥采⽤的顺序栈。
根据预测分析原理,LL(1)分析程序的实现关键在于分析栈和分析表是采⽤何种数据结构来实现。
分析表是⼀个矩阵,当我们要调⽤分析表来分析时,就根据栈顶的⾮终结符和当前输⼊的终结符来决定执⾏哪种过程。
具体设计思想如下:printStack()输出分析栈内内容;printinputString()输出⽤户输⼊的字符串;Pop()弹出栈顶元素;Push()向栈内添加⼀个元素;Search()查找⾮终结符集合VT 中是否存在输⼊的⾮终结符;yuCeFenXi()进⾏输⼊串的预测分析的主功能函数;M(char A, char a)查看预测分析表M[A,a]中是否存在相应产⽣式。
数据分析与预测方法实践指导书第1章数据分析概述 (3)1.1 数据分析的意义与价值 (3)1.2 数据分析的基本步骤 (4)1.3 数据分析的方法与工具 (4)第2章数据预处理 (5)2.1 数据清洗 (5)2.1.1 缺失值处理 (5)2.1.2 异常值处理 (5)2.1.3 重复值处理 (5)2.2 数据整合 (6)2.2.1 数据合并 (6)2.2.2 数据标准化 (6)2.2.3 数据一致性检查 (6)2.3 数据变换 (6)2.3.1 数据规范化 (6)2.3.2 数据离散化 (6)2.3.3 特征提取与选择 (6)2.4 数据规约 (6)2.4.1 数据降维 (7)2.4.2 数据压缩 (7)2.4.3 数据聚合 (7)第3章描述性统计分析 (7)3.1 频数分析与图表展示 (7)3.1.1 频数统计 (7)3.1.2 图表展示 (7)3.2 分布特性分析 (7)3.2.1 分布形态 (7)3.2.2 集中趋势 (7)3.2.3 离散程度 (8)3.3 关联性分析 (8)3.3.1 交叉表 (8)3.3.2 相关系数 (8)3.3.3 协方差矩阵 (8)3.4 异常值分析 (8)3.4.1 箱线图法 (8)3.4.2 基于规则的方法 (8)3.4.3 距离法 (8)3.4.4 统计模型法 (8)第4章假设检验与参数估计 (8)4.1 假设检验基本概念 (8)4.2 单样本检验 (9)4.4 参数估计 (9)第5章回归分析 (10)5.1 线性回归 (10)5.1.1 一元线性回归 (10)5.1.2 多元线性回归 (10)5.2 多元线性回归 (10)5.2.1 多元线性回归模型 (10)5.2.2 多元线性回归的假设检验 (10)5.2.3 应用实例 (10)5.3 逻辑回归 (10)5.3.1 逻辑回归模型 (10)5.3.2 模型评估与优化 (10)5.3.3 应用实例 (10)5.4 非线性回归 (11)5.4.1 非线性回归模型 (11)5.4.2 模型建立与参数估计 (11)5.4.3 应用实例 (11)第6章时间序列分析 (11)6.1 时间序列基本概念 (11)6.2 平稳性检验 (11)6.3 自相关与偏自相关分析 (11)6.4 时间序列预测方法 (12)第7章聚类分析 (12)7.1 聚类分析基本概念 (12)7.2 层次聚类法 (12)7.3 划分聚类法 (13)7.4 密度聚类法 (13)第8章分类与预测方法 (14)8.1 决策树 (14)8.1.1 基本原理 (14)8.1.2 特征选择 (14)8.1.3 决策树算法 (14)8.1.4 决策树剪枝 (14)8.2 随机森林 (14)8.2.1 基本原理 (14)8.2.2 随机森林算法 (14)8.2.3 超参数调优 (14)8.3 支持向量机 (14)8.3.1 基本原理 (15)8.3.2 核函数 (15)8.3.3 SVM算法 (15)8.4 神经网络 (15)8.4.1 基本原理 (15)8.4.3 神经网络算法 (15)8.4.4 神经网络优化方法 (15)第9章优化方法及其应用 (15)9.1 线性规划 (15)9.1.1 基本概念与理论 (15)9.1.2 线性规划的数学模型 (15)9.1.3 线性规划的求解方法 (16)9.2 非线性规划 (16)9.2.1 基本概念与理论 (16)9.2.2 非线性规划的数学模型 (16)9.2.3 非线性规划的求解方法 (16)9.3 整数规划 (16)9.3.1 基本概念与理论 (16)9.3.2 整数规划的数学模型 (16)9.3.3 整数规划的求解方法 (16)9.4 动态规划 (16)9.4.1 基本概念与理论 (16)9.4.2 动态规划的数学模型 (16)9.4.3 动态规划的求解方法 (17)第10章数据分析与预测在实际应用中的案例分析 (17)10.1 金融领域应用案例 (17)10.1.1 风险控制 (17)10.1.2 信用评估 (17)10.1.3 投资决策 (17)10.2 电商领域应用案例 (17)10.2.1 用户行为分析 (17)10.2.2 推荐系统 (17)10.2.3 库存管理 (18)10.3 医疗领域应用案例 (18)10.3.1 疾病预测 (18)10.3.2 药物研发 (18)10.3.3 医疗资源分配 (18)10.4 能源领域应用案例 (18)10.4.1 能源消耗预测 (18)10.4.2 电力负荷预测 (18)10.4.3 新能源利用 (18)第1章数据分析概述1.1 数据分析的意义与价值数据分析作为一种科学的方法论,在现代社会的各个领域具有极高的应用价值。
预测分析方法预测是根据研究对象发展变化的实际数据和历史资料,运用现代的科学理论和方法,以及各种经验、判断和知识,对事物在未来一定时期内可能变化情况进行推测、估计和分析。
预测分析的实质就是充分分析、理解事物发展变化的规律,根据事物的过去和现在估计未来,根据已知预测未知,从而减少对未来事物认识的不确定性,以指导我们的决策行动,减少决策的盲目性。
一、预测方法的分类预测和决策可以根据经验和直觉作出。
但是现代社会的发展使得系统结构日益复杂,变化过程中存在着极大的不确定性和随机性,这就使得我们在系统的组织、管理中凭经验、直觉作出决策并获得成功的可能性大大减小。
为了在错综复杂、急剧变化的环境中减少决策失误、改善管理调控,预测的理论和方法随着实践的变化有了迅速的发展,形成了一套科学的预测方法。
由于预测对象、时间、范围、性质等的不同,可以有不同的预测方法分类,根据方法本身的性质特点,我们可以将公共管理中的常用预测方法分为3大类。
第一类称为定性预测方法。
这种方法主要根据人们对系统过去和现在的经验、判断和直觉作出预测。
第二类称为时间序列分析预测方法。
这类方法主要是根据系统对象随时间变化的历史资料(如统计数据、实验数据和变化趋势等),只考虑系统变量随时间的发展变化规律,对其未来作出预测。
第三类称为因果关系预测方法。
系统变量之间存在着某种前因后果关系,找出影响某种结果的一个或者几个因素,建立起它们之间的数学模型,然后根据自变量的变化预测结果变量的变化。
因果关系模型的因变量和自变量在时间上是同步的,即因变量的预测值要由并进的自变量的值来旁推。
二、预测分析的一般步骤预测分析是一种科学预测,是对系统对象发展、演变的客观规律的认识和分析过程。
因此,预测分析应该建立在科学的理论基础之上,采用合理的分析、测算以及评价方法和手段。
预测分析技术的内涵应该包括它所遵循的理论、预测对象的历史和现状资料与数据、所能采用的计算方法或分析判断方法、预测方法和结果的评价与检验等要素。
《数据分析》实验报告三实验报告三:数据分析实验目的:本实验旨在通过对一批数据进行分析,探索数据之间的关系、趋势和规律,从而为决策提供科学依据。
实验方法:1. 数据收集:从数据库中获取相关数据。
2. 数据清洗:对数据进行去重、缺失值处理和异常值处理。
3. 数据预处理:对数据进行标准化、归一化等预处理操作,以保证数据的可比性。
4. 数据分析:采用统计学和机器学习等方法对数据进行分析,包括描述性统计分析、相关性分析、回归分析等。
5. 结果展示:将分析结果以表格、图表等形式进行可视化展示,以便于观察和理解。
实验步骤:1. 数据收集:从公司A的销售系统中获取了过去一年的销售数据,包括销售额、销售时间、销售地区等信息。
2. 数据清洗:对数据进行去重,并对缺失值和异常值进行处理,确保数据的准确性和完整性。
3. 数据预处理:对销售额数据进行了归一化处理,使得数据符合正态分布。
4. 数据分析:a. 描述性统计分析:对销售额进行了统计分析,得出平均销售额、最大销售额、最小销售额等数据。
b. 相关性分析:通过计算销售额与销售时间、销售地区之间的相关系数,探索二者之间的关系。
c. 回归分析:利用线性回归模型,分析销售时间对销售额的影响,并进行模型评估和预测。
5. 结果展示:将分析结果以表格和图表的形式展示出来,其中包括描述性统计结果、相关系数矩阵、回归模型的参数等。
实验结果:1. 描述性统计分析结果:- 平均销售额:10000元- 最大销售额:50000元- 最小销售额:100元- 销售额标准差:5000元2. 相关性分析结果:- 销售额与销售时间的相关系数为0.8,表明销售时间对销售额有较强的正相关性。
- 销售额与销售地区的相关系数为0.5,表明销售地区对销售额有适度的正相关性。
3. 回归分析结果:- 线性回归模型:销售额 = 500 + 100 * 销售时间- 模型评估:通过计算均方差和决定系数,评估回归模型的拟合优度。
利用回归分析预测实验结果的趋势在科学研究和实验中,预测实验结果的趋势是一项重要的任务。
回归分析作为一种常用的统计方法,可以帮助我们探索变量之间的关系,并通过数学模型预测未来的结果。
本文将介绍回归分析的基本原理和应用,以及如何利用回归分析预测实验结果的趋势。
一、回归分析的基本原理回归分析是一种统计方法,用于研究自变量与因变量之间的关系。
在回归分析中,自变量是我们想要用来预测和解释因变量的变化的变量,因变量是我们想要预测的变量。
回归分析的目标是建立一个数学模型,可以通过自变量的取值预测因变量的取值。
回归分析的基本原理是最小二乘法。
最小二乘法通过将自变量与因变量的观测值代入数学模型,计算出预测值与观测值之间的差异(残差),然后调整模型参数,使得残差的平方和最小化。
最小二乘法可以得出最优的模型参数,并基于这个模型来预测未来的结果。
二、回归分析的应用回归分析广泛应用于各个领域的科学研究和实验中。
它可以帮助我们更好地理解变量之间的关系,预测未来的趋势,并作出更合理的决策。
以下是几个常见的应用领域:1. 经济学:回归分析可以用来研究经济变量之间的关系,如GDP与通货膨胀率、利率与投资额等。
通过回归分析,我们可以预测未来的经济趋势,评估政策的效果,并制定相应的经济政策。
2. 医学研究:回归分析可以用来研究生物医学的相关性,如药物剂量与疗效、生活方式与慢性疾病的关系等。
通过回归分析,我们可以预测治疗效果,指导临床决策,并优化治疗方案。
3. 社会科学:回归分析可以用来研究社会学、心理学、教育学等领域的问题,如家庭收入对子女学业成绩的影响、领导风格对员工满意度的影响等。
通过回归分析,我们可以预测社会现象的发展趋势,为政策制定和管理提供依据。
三、利用回归分析预测实验结果的趋势在科学研究和实验中,我们经常需要通过实验数据来预测未来的趋势。
回归分析可以帮助我们利用历史数据或实验结果,建立一个模型,并用这个模型来预测未来的结果。
如何进行实验数据分析实验数据分析是科研工作中至关重要的一环,它可以帮助我们从大量的实验数据中提取有用的信息和结论。
本文将介绍一些常用的实验数据分析方法,以及如何使用这些方法来解读实验结果。
一、数据整理与预处理在进行实验数据分析之前,首先需要对所获得的数据进行整理和预处理。
这一步骤的目的是确保数据的质量和可靠性。
常见的数据整理和预处理方法包括:1. 数据清洗:删除或修正异常值、缺失值等不符合要求的数据。
2. 数据标准化:通过将数据进行标准化处理,可以消除因不同单位或量纲带来的影响,使得数据具有可比性。
3. 数据平滑:通过使用滤波算法等方法,可以去除数据中的噪声,使得数据平滑化。
4. 数据归一化:将数据缩放到某个特定的范围,以便进行后续的分析和比较。
二、数据可视化与描述统计在进行实验数据分析时,数据可视化和描述统计是最常用的分析方法之一。
通过直观地展示数据的分布规律和趋势,可以更好地理解实验结果。
以下是一些常用的数据可视化和描述统计方法:1. 直方图:用来描述数据的分布情况。
通过将数据分成若干个区间,统计落入每个区间内的数据个数,从而得到数据的频数分布。
2. 散点图:用来描述两个变量之间的关系。
通过在坐标系中绘制数据点,可以直观地观察数据的分布和趋势。
3. 箱线图:主要用于观察数据的离散程度和异常值。
箱线图包括最小值、最大值、中位数、上下四分位数等统计指标。
4. 均值与标准差:用于描述数据的中心位置和离散程度。
均值表示数据的平均水平,标准差表示数据的分散程度。
三、统计分析方法除了数据可视化和描述统计,统计分析方法也是实验数据分析的重要内容。
它可以帮助我们判断实验结果是否具有显著性差异,以及推断结果的可靠性。
以下是一些常用的统计分析方法:1. t检验:用于判断两组数据的均值是否存在显著差异。
当两组数据满足正态分布和方差齐性的条件时,可以使用t检验进行分析。
2. 方差分析:用于判断多组数据的均值是否存在显著差异。
一、分析语法分析部分我们我们采用LL(1)方法实现,采用LL(1)方法实现语法发分析要求文法满足以下要求:一个文法能否用确定的自顶向下分析与文法中相同左部的每个产生式右部的开始符号集合有关,当有右部能=*=>ε时则与其左部非终结符的后跟符号集合也有关,此外在产生式中不存在左递归,无回溯。
它的基本思想是从左到右扫描源程序,同时从识别符号开始生成句子的最左推导,并只向前查看一个输入符号,便能唯一确定应选择的规则。
下面将确切地定义满足确定的自顶向下分析条件的文法即LL(1)文法及LL(1)文法的判别并介绍如何对非LL(1)文法进行等价变换问题,也就是消除一个文法中的左递归和左公共因子。
注意:一个文法中含有左递归和左公共因子绝对不是LL(1)文法,所以也就不可能用确定的自顶向下分析法,对此结论可以证明。
然而,某些含有左递归和左公共因子的文法在通过等价变换把它们消除以后可能变为LL(1)文法,但需要用LL(1)文法的定义判别,也就是说文法中不含左递归和左公共因子,只是LL(1)文法的必要条件。
LL(1) 文法的定义(5种定义):一个文法符号串的开始符号集合定义如下:定义1.设G=(VT,VN,S,P)是上下文无关文法,α是任意的文法符号串,FIRST(α)是从α推导出的串的开始符号的终结符集合。
FIRST(α)={a|α=*=>aβ,a∈VT,α,β∈V*}若α=*=>ε,则规定ε∈FIRST(α).当一个文法中相同左部非终结符的右部存在能=*=>ε的情况则必须知道该非终结符的后跟符号的集合中是否含有其它右部开始符号集合的元素。
为此,我们定义一个文法非终结符的后跟符号的集合如下:定义2.设G=(VT,VN,S,P)是上下文无关文法,A∈VN,S是开始符号FOLLOW(A)={a|S=*=>μAβ,且a∈VT,a∈FIRST(β),μ∈VT* ,β∈V+}若S=*=>μAβ,且βε, 则#∈FOLLOW(A)。
也可定义为:FOLLOW(A)={a|S=*=> …Aa…,a ∈VT}若有S=*=> …A,则规定#∈FOLLOW(A)这里我们用'#'作为输入串的结束符,或称为句子括号,如:#输入串#。
定义3.给定上下文无关文法的产生式A→α, A∈VN,α∈V*, 若α==>ε,则SELECT(A →α)=FIRST(α)如果α=*=>ε,则SELECT(A→α)=FIRST(αε)∪FOLLOW(A)。
FIRST(αε)表示FIRST(α)的非{ε}元素。
更进一步可以看出能够使用自顶向下分析技术必须使文法满足如下条件,我们称满足条件的文法为LL(1)文法,其定义为:定义4.一个上下文无关文法是LL(1)文法的充分必要条件是:对每个非终结符A的两个不同产生式,A→α, A→β,满足SELECT(A→α)∩SELECT(A →β)=空,其中α,β不同时能ε.定义5. LL(1)文法也可定义为:一个文法G是LL(1)的,当且仅当对于G的每一个非终结符A的任何两个不同产生式A→α|β,下面的条件成立:(1)FIRST(α)∩FIRST(β)= 空,也就是α和β推导不出以某个相同的终结符a为首的符号串;它们不应该都能推出空字ε.(2)假若β=>ε那么,FIRST(α)∩FOLLOW(A)=空也就是,若β=>ε则α所能推出的串的首符号不应在FOLLOW(A)中。
二、算法(1)读入文法(2)判断正误(3)若无误,判断是否为LL(1)文法(4)若是,构造分析表;根据下面LL(1)文法,对输入串w: (i+i)*(i+i)+i*i进行LL(1)分析1、先手工建立LL(1)分析表;2LL(1)文法G为:E →TE’E’→+TE’|εT →FT’T’→*FT’|εF →(E)|id分析算法:输入:串w和文法G的分析表M。
输出:如果W属于L(G),则输出W的最左推导,否则报告错误。
方法:开始时,#S在分析栈中,其中S是文法的开始符号,在栈顶;令指针ip指向W#的第一个符号;repeat让X等于栈顶符号,a为ip所指向的符号;if X 是终结符号或# thenIf X=a then 把X从栈顶弹出并使ip指向下一个输入符号else error()else /*X 是非终结符号*/if M[x,a]=Xày1y2…yk then begin从栈中弹出X;把yk,yk-1,…,y1压入栈,y1在栈顶;输出产生式Xày1y2…yk;endelse error()until X=# /*栈空*/语法分析的流程算法三、设计目的:(1)理解和掌握LL(1)语法分析方法的基本原理;根据给出的LL(1)文法,掌握LL(1)分析表的构造及分析过程的实现。
(2)掌握预测分析程序如何使用分析表和栈联合控制实现LL(1)分析。
四、实现环境和要求选择实习环境为486以上CPU,4M内存,TURBO C2.0语言. 实现程序见附录.具体的实现要求:(1)对输入文法,它能判断是否为LL(1)文法,若是,则转(2);否则报错并终止;(2)输入已知文法,由程序自动生成它的LL(1)分析表;(3)对于给定的输入串,应能判断识别该串是否为给定文法的句型。
附录/*****************************************************预测分析程序(语法分析程序),分析对象为C语言源程序文件。
该分析程序有18部分组成:《1》首先定义各种需要用到的常量和变量;《2》判断一个字符是否在指定字符串中;《3》得到一个不是非终结符的符号;《4》分解含有左递归的产生式;《5》分解不含有左递归的产生式;《6》读入一个文法;《7》将单个符号或符号串并入另一符号串;《8》求所有能直接推出^的符号;《9》求某一符号能否推出‘^ ’;《10》判断读入的文法是否正确;《11》求单个符号的FIRST;《12》求各产生式右部的FIRST;《13》求各产生式左部的FOLLOW;《14》判断读入文法是否为一个LL(1)文法;《15》构造分析表M;《16》总控算法;《17》一个用户调用函数;《18》主函数;程序如下:#include<stdlib.h>#include<stdio.h>#include<string.h>int count=0; /*分解的产生式的个数*/int number; /*所有终结符和非终结符的总数*/char start; /*开始符号*/char termin[50]; /*终结符号*/char non_ter[50]; /*非终结符号*/char v[50]; /*所有符号*/char left[50]; /*左部*/char right[50][50]; /*右部*/char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/ char first1[50][50]; /*所有单个符号的FIRST集合*/char select[50][50]; /*各单个产生式的SELECT集合*/char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/char empty[20]; /*记录可直接推出^的符号*/char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/ int validity=1; /*表示输入文法是否有效*/int ll=1; /*表示输入文法是否为LL(1)文法*/int M[20][20]; /*分析表*/char choose; /*用户输入时使用*/char empt[20]; /*求_emp()时使用*/char fo[20]; /*求FOLLOW集合时使用*//*******************************************判断一个字符是否在指定字符串中********************************************/int in(char c,char *p){int i;if(strlen(p)==0)return(0);for(i=0;;i++){if(p[i]==c)return(1); /*若在,返回1*/if(i==strlen(p))return(0); /*若不在,返回0*/}}/*******************************************得到一个不是非终结符的符号********************************************/char c(){char c='A';while(in(c,non_ter)==1)c++;return(c);}/*******************************************分解含有左递归的产生式********************************************/void recur(char *point){ /*完整的产生式在point[]中*/int j,m=0,n=3,k;char temp[20],ch;ch=c(); /*得到一个非终结符*/k=strlen(non_ter);non_ter[k]=ch;non_ter[k+1]='\0';for(j=0;j<=strlen(point)-1;j++){if(point[n]==point[0]){ /*如果‘|’后的首符号和左部相同*/ for(j=n+1;j<=strlen(point)-1;j++){while(point[j]!='|'&&point[j]!='\0')temp[m++]=point[j++];left[count]=ch;memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';m=0;count++;if(point[j]=='|'){n=j+1;break;}}}else{ /*如果‘|’后的首符号和左部不同*/ left[count]=ch;right[count][0]='^';right[count][1]='\0';count++;for(j=n;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';printf(" count=%d ",count);m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';count++;m=0;}}}/*******************************************分解不含有左递归的产生式********************************************/void non_re(char *point){int m=0,j;char temp[20];for(j=3;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;m=0;}/*******************************************读入一个文法********************************************/char grammer(char *t,char *n,char *left,char right[50][50]) {char vn[50],vt[50];char s;char p[50][50];int i,j,k;printf("\n请输入文法的非终结符号串:");scanf("%s",vn);getchar();i=strlen(vn);memcpy(n,vn,i);n[i]='\0';printf("请输入文法的终结符号串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf("请输入文法的开始符号:");scanf("%c",&s);getchar();printf("请输入文法产生式的条数:");scanf("%d",&i);getchar();for(j=1;j<=i;j++){printf("请输入文法的第%d条(共%d条)产生式:",j,i);scanf("%s",p[j-1]);getchar();}for(j=0;j<=i-1;j++)if(p[j][1]!='-'||p[j][2]!='>'){ printf("\ninput error!");validity=0;return('\0');} /*检测输入错误*/for(k=0;k<=i-1;k++){ /*分解输入的各产生式*/if(p[k][3]==p[k][0])recur(p[k]);elsenon_re(p[k]);}return(s);}/*******************************************将单个符号或符号串并入另一符号串********************************************/void merge(char *d,char *s,int type){ /*d是目标符号串,s是源串,type=1,源串中的‘^ ’一并并入目串;type=2,源串中的‘^ ’不并入目串*/int i,j;for(i=0;i<=strlen(s)-1;i++){if(type==2&&s[i]=='^');else{for(j=0;;j++){if(j<strlen(d)&&s[i]==d[j])break;if(j==strlen(d)){d[j]=s[i];d[j+1]='\0';break;}}}}}/*******************************************求所有能直接推出^的符号********************************************/void emp(char c){ /*即求所有由‘^ ’推出的符号*/ char temp[10];int i;for(i=0;i<=count-1;i++){if(right[i][0]==c&&strlen(right[i])==1){temp[0]=left[i];temp[1]='\0';merge(empty,temp,1);emp(left[i]);}}}/*******************************************求某一符号能否推出‘^ ’********************************************/int _emp(char c){ /*若能推出,返回1;否则,返回0*/int i,j,k,result=1,mark=0;char temp[20];temp[0]=c;temp[1]='\0';merge(empt,temp,1);if(in(c,empty)==1)return(1);for(i=0;;i++){if(i==count)return(0);if(left[i]==c) /*找一个左部为c的产生式*/{j=strlen(right[i]); /*j为右部的长度*/if(j==1&&in(right[i][0],empty)==1)return(1);else if(j==1&&in(right[i][0],termin)==1)return(0);else{for(k=0;k<=j-1;k++)if(in(right[i][k],empt)==1)mark=1;if(mark==1)continue;else{for(k=0;k<=j-1;k++){result*=_emp(right[i][k]);temp[0]=right[i][k];temp[1]='\0';merge(empt,temp,1);}}}if(result==0&&i<count)continue;else if(result==1&&i<count)return(1);}}}/*******************************************判断读入的文法是否正确********************************************/int judge(){int i,j;for(i=0;i<=count-1;i++){if(in(left[i],non_ter)==0){ /*若左部不在非终结符中,报错*/printf("\nerror1!");validity=0;return(0);}for(j=0;j<=strlen(right[i])-1;j++){if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='^'){ /*若右部某一符号不在非终结符、终结符中且不为‘^ ’,报错*/ printf("\nerror2!");validity=0;return(0);}}}return(1);}/*******************************************求单个符号的FIRST********************************************/void first2(int i){ /*i为符号在所有输入符号中的序号*/char c,temp[20];int j,k,m;c=v[i];char ch='^';emp(ch);if(in(c,termin)==1) /*若为终结符*/{first1[i][0]=c;first1[i][1]='\0';}else if(in(c,non_ter)==1) /*若为非终结符*/{for(j=0;j<=count-1;j++){if(left[j]==c){if(in(right[j][0],termin)==1||right[j][0]=='^'){temp[0]=right[j][0];temp[1]='\0';merge(first1[i],temp,1);}else if(in(right[j][0],non_ter)==1){if(right[j][0]==c)continue;for(k=0;;k++)if(v[k]==right[j][0])break;if(f[k]=='0'){first2(k);f[k]='1';}merge(first1[i],first1[k],2);for(k=0;k<=strlen(right[j])-1;k++){empt[0]='\0';if(_emp(right[j][k])==1&&k<strlen(right[j])-1){for(m=0;;m++)if(v[m]==right[j][k+1])break;if(f[m]=='0'){first2(m);f[m]='1';}merge(first1[i],first1[m],2);}else if(_emp(right[j][k])==1&&k==strlen(right[j])-1){temp[0]='^';temp[1]='\0';merge(first1[i],temp,1);}elsebreak;}}}}}f[i]='1';}/*******************************************求各产生式右部的FIRST********************************************/void FIRST(int i,char *p){int length;int j,k,m;char temp[20];length=strlen(p);if(length==1) /*如果右部为单个符号*/ {if(p[0]=='^'){if(i>=0){first[i][0]='^';first[i][1]='\0';}else{TEMP[0]='^';TEMP[1]='\0';}}else{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0){memcpy(first[i],first1[j],strlen(first1[j]));first[i][strlen(first1[j])]='\0';}else{memcpy(TEMP,first1[j],strlen(first1[j]));TEMP[strlen(first1[j])]='\0';}}}else /*如果右部为符号串*/ {for(j=0;;j++)if(v[j]==p[0])break;if(i>=0)merge(first[i],first1[j],2);elsemerge(TEMP,first1[j],2);for(k=0;k<=length-1;k++){empt[0]='\0';if(_emp(p[k])==1&&k<length-1){for(m=0;;m++)if(v[m]==right[i][k+1])break;if(i>=0)merge(first[i],first1[m],2);elsemerge(TEMP,first1[m],2);}else if(_emp(p[k])==1&&k==length-1){temp[0]='^';temp[1]='\0';if(i>=0)merge(first[i],temp,1);elsemerge(TEMP,temp,1);}else if(_emp(p[k])==0)break;}}}/*******************************************求各产生式左部的FOLLOW********************************************/void FOLLOW(int i){int j,k,m,n,result=1;char c,temp[20];c=non_ter[i]; /*c为待求的非终结符*/temp[0]=c;temp[1]='\0';merge(fo,temp,1);if(c==start){ /*若为开始符号*/temp[0]='#';temp[1]='\0';merge(follow[i],temp,1);}for(j=0;j<=count-1;j++){if(in(c,right[j])==1) /*找一个右部含有c的产生式*/{for(k=0;;k++)if(right[j][k]==c)break; /*k为c在该产生式右部的序号*/for(m=0;;m++)if(v[m]==left[j])break; /*m为产生式左部非终结符在所有符号中的序号*/ if(k==strlen(right[j])-1){ /*如果c在产生式右部的最后*/if(in(v[m],fo)==1){merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}else{ /*如果c不在产生式右部的最后*/for(n=k+1;n<=strlen(right[j])-1;n++){empt[0]='\0';result*=_emp(right[j][n]);}if(result==1){ /*如果右部c后面的符号串能推出^*/if(in(v[m],fo)==1){ /*避免循环递归*/merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}for(n=k+1;n<=strlen(right[j])-1;n++)temp[n-k-1]=right[j][n];temp[strlen(right[j])-k-1]='\0';FIRST(-1,temp);merge(follow[i],TEMP,2);}}}F[i]='1';}/*******************************************判断读入文法是否为一个LL(1)文法********************************************/int ll1(){int i,j,length,result=1;char temp[50];for(j=0;j<=49;j++){ /*初始化*/first[j][0]='\0';follow[j][0]='\0';first1[j][0]='\0';select[j][0]='\0';TEMP[j]='\0';temp[j]='\0';f[j]='0';F[j]='0';}for(j=0;j<=strlen(v)-1;j++)first2(j); /*求单个符号的FIRST集合*/ printf("\nfirst1:");for(j=0;j<=strlen(v)-1;j++)printf("%c:%s ",v[j],first1[j]);printf("\nempty:%s",empty);printf("\n:::\n_emp:");for(j=0;j<=strlen(v)-1;j++)printf("%d ",_emp(v[j]));for(i=0;i<=count-1;i++)FIRST(i,right[i]); /*求FIRST*/printf("\n");for(j=0;j<=strlen(non_ter)-1;j++){ /*求FOLLOW*/if(fo[j]==0){fo[0]='\0';FOLLOW(j);}}printf("\nfirst:");for(i=0;i<=count-1;i++)printf("%s ",first[i]);printf("\nfollow:");for(i=0;i<=strlen(non_ter)-1;i++)printf("%s ",follow[i]);for(i=0;i<=count-1;i++){ /*求每一产生式的SELECT集合*/ memcpy(select[i],first[i],strlen(first[i]));select[i][strlen(first[i])]='\0';for(j=0;j<=strlen(right[i])-1;j++)result*=_emp(right[i][j]);if(strlen(right[i])==1&&right[i][0]=='^')result=1;if(result==1){for(j=0;;j++)if(v[j]==left[i])break;merge(select[i],follow[j],1);}}printf("\nselect:");for(i=0;i<=count-1;i++)printf("%s ",select[i]);memcpy(temp,select[0],strlen(select[0]));temp[strlen(select[0])]='\0';for(i=1;i<=count-1;i++){ /*判断输入文法是否为LL(1)文法*/length=strlen(temp);if(left[i]==left[i-1]){merge(temp,select[i],1);if(strlen(temp)<length+strlen(select[i]))return(0);}else{temp[0]='\0';memcpy(temp,select[i],strlen(select[i]));temp[strlen(select[i])]='\0';}}return(1);}/*******************************************构造分析表M********************************************/void MM(){int i,j,k,m;for(i=0;i<=19;i++)for(j=0;j<=19;j++)M[i][j]=-1;i=strlen(termin);termin[i]='#'; /*将#加入终结符数组*/termin[i+1]='\0';for(i=0;i<=count-1;i++){for(m=0;;m++)if(non_ter[m]==left[i])break; /*m为产生式左部非终结符的序号*/ for(j=0;j<=strlen(select[i])-1;j++){if(in(select[i][j],termin)==1){for(k=0;;k++)if(termin[k]==select[i][j])break; /*k为产生式右部终结符的序号*/ M[m][k]=i;}}}}/*******************************************总控算法********************************************/void syntax(){int i,j,k,m,n,p,q;char ch;char S[50],str[50];printf("请输入该文法的句型:");scanf("%s",str);getchar();i=strlen(str);str[i]='#';str[i+1]='\0';S[0]='#';S[1]=start;S[2]='\0';j=0;ch=str[j];while(1){if(in(S[strlen(S)-1],termin)==1){if(S[strlen(S)-1]!=ch){printf("\n该符号串不是文法的句型!");return;}else if(S[strlen(S)-1]=='#'){printf("\n该符号串是文法的句型.");return;}else{S[strlen(S)-1]='\0';j++;ch=str[j];}}else{for(i=0;;i++)if(non_ter[i]==S[strlen(S)-1])break;for(k=0;;k++){if(termin[k]==ch)break;if(k==strlen(termin)){printf("\n词法错误!");return;}}if(M[i][k]==-1){printf("\n语法错误!");return;}else{m=M[i][k];if(right[m][0]=='^')S[strlen(S)-1]='\0';else{p=strlen(S)-1;q=p;for(n=strlen(right[m])-1;n>=0;n--)S[p++]=right[m][n];S[q+strlen(right[m])]='\0';}}}printf("\nS:%s str:",S);for(p=j;p<=strlen(str)-1;p++)printf("%c",str[p]);printf(" ");}}/*******************************************一个用户调用函数********************************************/void menu(){syntax();printf("\n是否继续?(y or n):");scanf("%c",&choose);getchar();while(choose=='y'){menu();}}/*******************************************主函数********************************************/void main(){int i,j;start=grammer(termin,non_ter,left,right); /*读入一个文法*/ printf("count=%d",count);printf("\nstart:%c",start);strcpy(v,non_ter);strcat(v,termin);printf("\nv:%s",v);printf("\nnon_ter:%s",non_ter);printf("\ntermin:%s",termin);printf("\nright:");for(i=0;i<=count-1;i++)printf("%s ",right[i]);printf("\nleft:");for(i=0;i<=count-1;i++)printf("%c ",left[i]);if(validity==1)validity=judge();printf("\nvalidity=%d",validity);if(validity==1){printf("\n文法有效");ll=ll1();printf("\nll=%d",ll);if(ll==0)printf("\n该文法不是一个LL1文法!");else{MM();printf("\n");for(i=0;i<=19;i++)for(j=0;j<=19;j++)if(M[i][j]>=0)printf("M[%d][%d]=%d ",i,j,M[i][j]);printf("\n");menu();}}}5.执行结果(1)输入一个文法(2)输入一个符号串(3)再次输入一个符号串,然后退出程序。