编译原理实验一、 程序设计语言认知实验报告

一、实验目的

了解程序设计语言的发展历史,了解不同程序设计语言的各自特点:感受编译执行和解释执行两种不同的执行方式,初步体验语言对编译器设计的影响,为后续编译程序的设计和开发奠定良好的基础。

二、实验内容

分别使用C、Java、Python实现矩阵乘法,对采用这几种语言实现的编程效率,程序的规模,程序的运行效率进行对比分析。方便起见,本次实验采用的都是n维方阵的矩阵乘法。同时为了保证实验的合理性,所有矩阵乘法均未采用其他库。

本次实验的方阵维度分别为:10、100、500、1000,为了减少误差,每组数据均重复十次并取时间的平均值。

三、实验环境

Linux系统(Ubuntu、Debian、Gentoo等系统均可),gcc 7.3.0,g++ 7.3.0,Java JDK 1.8,Python 3.6(以上编译器\解释器均可使用更高版本)。

四、数据准备

本次实验数据均在data文件夹下,由该文件夹下的produce_data.py脚本生成,生成的数据范围为[-100, 100)。如需更多实验数据,可自行修改脚本内容进行数据生成。

 

文件名

含义

matrix10.txt

维度为10的方阵

matrix100.txt

维度为100的方阵

matrix500.txt

维度为500的方阵

matrix1000.txt

维度为1000的方阵

五、实验过程设计

本实验分别使用C、Java、Python实现矩阵乘法,c语言由Dev-C++执行, Java由idea执行,Python由Visual Studio Code执行,本次实验采用的都是n维方阵的矩阵乘法,方阵维度分别为:10、100、500、1000,从矩阵计算函数开始执行计时,到执行完毕结束计时,打印出计算时间,为了减少误差,每组数据均重复十次并取时间的平均值。

六、程序设计及实现

Python

import time
def readFile():
    data_list = []
    with open("./matrix500.txt", 'r') as f:
        lines = f.readlines()
        for line in lines:
            line = line.rstrip()
            intData_List = list(map(int,line.split(" ")))
            data_list.append(intData_List)
    return data_list

def matrixMul(A, B):
    C = [[0] * len(B[0]) for i in range(len(A))]
   
    start = time.perf_counter()     
    for i in range(len(A)):
               for j in range(len(B[0])):
                        for k in range(len(B)):
                C[i][j] += A[i][k] * B[k][j]
    end = time.perf_counter() 
    return end-start

if __name__ == '__main__':
    A = readFile()
    t = matrixMul(A, A)
    print("time = " + str(t) + "s")

Java

package 矩阵;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class Juzhen {
    static int N = 10;
    int[][] m = new int[N][N];
    int[][] r = new int[N][N];

    public Juzhen() throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("src/矩阵/matrix10.txt"));
        List<String> list = new ArrayList<String>();
        String line = null;
        while((line = br.readLine())!=null){
            list.add(line);
        }
        br.close();
        for (int i = 0; i < N; i++) {
            String[] arr = list.get(i).trim().split(" ");
            for (int j = 0; j < N; j++) {
                m[i][j] = Integer.parseInt(arr[j]);
            }

        }
    }
    public void MatrixMulti(){
        long start,end;
        double t = 0;
        start = System.nanoTime();

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                for (int k = 0; k < N; k++) {
                    r[i][j] += m[i][k] * m[k][j];
                }
            }
        }
        end = System.nanoTime();
        t = (double)(end - start)/1000000000;
        System.out.println("time = " + t + "s");
    }
    public static void main(String[] args) throws IOException {
        Juzhen r = new Juzhen();
        r.MatrixMulti();
    }
}

C

#include<stdio.h>

#include<time.h>

#define N 10

static int a[N][N],b[N][N];

void readFile()

{

     int x,y;

     FILE *file=fopen("matrix10.txt","r");

     for(x=0;x<N;x++)

          for(y=0;y<N;y++)

               fscanf(file,"%d",&a[x][y]);

     fclose(file);

 }

 void mul()

 {

    int i,j,k;

    for(i=0;i<N;i++)

    {

         for(j=0;j<N;j++)

         {

              b[i][j] = 0;

              for(k=0;k<N;k++)

                   b[i][j] += a[i][k] * a[k][j];

           }      

      }

 }

 int main()

 {

    int i,time[10];

    clock_t start,end;

    readFile();

    start = clock();

    mul();

    end = clock();

    printf("time=%f\n",((double)end-start)/1000);

 }

七、实验结果及分析

Python

N

10

100

500

1000

1

0.0002438

0.172358

19.65427

163.9216

2

0.0002352

0.168675

19.65298

163.7512

3

0.0002298

0.178036

19.65433

163.6524

4

0.0002438

0.173581

19.65589

163.5193

5

0.0002512

0.172653

19.65281

163.6217

6

0.0002487

0.174702

19.65094

163.4518

7

0.0002365

0.172974

19.65853

163.6539

8

0.0002279

0.172853

19.65706

163.5210

9

0.0002394

0.175673

19.65573

163.6218

10

0.0002447

0.169228

19.65924

163.3516

平均

0.0002

0.17

19.65

163.6

JAVA

N

10

100

500

1000

1

0.0000547

0.008729

0.222921

2.257617

2

0.0000492

0.008135

0.226725

2.256743

3

0.0000537

0.009169

0.222178

2.247857

4

0.0000584

0.009054

0.222836

2.259637

5

0.0000463

0.007247

0.223849

2.257346

6

0.0000582

0.008315

0.225821

2.258659

7

0.0000527

0.008292

0.222672

2.260627

8

0.0000519

0.007346

0.228923

2.256752

9

0.0000537

0.008791

0.227241

2.252926

10

0.0000482

0.008213

0.223921

2.247617

平均

0.00005

0.008

0.22

2.25

C

N

10

100

500

1000

1

0.0

0.0

0.003

0.009

2

0.0

0.0

0.003

0.010

3

0.0

0.0

0.004

0.013

4

0.0

0.0

0.002

0.009

5

0.0

0.0

0.004

0.011

6

0.0

0.0

0.003

0.010

7

0.0

0.0

0.003

0.009

8

0.0

0.0

0.002

0.010

9

0.0

0.0

0.002

0.012

10

0.0

0.0

0.004

0.009

平均

0.0

0.0

0.003

0.010

通过上述实验数据的对比,清晰得展现出了当数组维数较少时三种语言的执行速度差不多,随着维数增大,表现出C语言执行速度最快,Python执行速度最慢。

八、实验心得体会

通过这次实验,我了解了不同程序设计语言的各自特点并感受到编译执行和解释执行两种不同的执行方式,初步体验语言对编译器设计的影响,从数据可以看出Python作为一门解释型语言确实执行效率很慢,但是Python代码相比C语言、Java语言代码稍微简短一些,另外Java JIT编译器会自动执行优化,但对于GCC编译器必须显式设置优化标志才可以。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实验目的: 1.理解词法分析程序的基本原理和算法。 2.掌握Flex工具的使用方法。 3.掌握正则表达式的使用方法。 实验要求: 1.设计一个简单的词法分析程序,能够识别出以下关键字:if, else, for, while, do, break, continue, return。 2.能够识别出整数、浮点数、标识符、运算符、界符等。 3.能够对输入的代码进行词法分析并输出结果。 实验过程: 1.安装Flex工具。 2.编写词法分析器的规则。 3.编写测试程序。 4.使用Flex工具生成词法分析器。 5.编译并运行测试程序。 实验步骤: 1.安装Flex工具。 在Ubuntu系统中,可以使用以下命令安装Flex工具: ``` sudo apt-get install flex ``` 2.编写词法分析器的规则。 在本实验中,我们需要识别出以下关键字: if, else, for, while, do, break, continue, return 可以使用以下正则表达式进行匹配: ``` "if" {return IF;} "else" {return ELSE;} "for" {return FOR;} "while" {return WHILE;} "do" {return DO;} "break" {return BREAK;} "continue" {return CONTINUE;} "return" {return RETURN;} ``` 我们还需要识别出整数和浮点数。可以使用以下正则表达式进行匹配: ``` [0-9]+ {yylval.num = atoi(yytext); return INT;} [0-9]+"."[0-9]+ {yylval.fnum = atof(yytext); return FLOAT;} ``` 其中,yylval是Flex工具自带的一个全局变量,用于存储识别出的标识符、整数或浮点数的值。 我们还需要识别出运算符和界符。可以使用以下正则表达式进行匹配: ``` "+" {return ADD;} "-" {return SUB;} "*" {return MUL;} "/" {return DIV;} "%" {return MOD;} "=" {return ASSIGN;} ">" {return GT;} ">=" {return GE;} "<" {return LT;} "<=" {return LE;} "!=" {return NE;} "==" {return EQ;} ";" {return SEMICOLON;} "," {return COMMA;} "(" {return LPAREN;} ")" {return RPAREN;} "{" {return LBRACE;} "}" {return RBRACE;} ``` 最后,我们需要识别出标识符。可以使用以下正则表达式进行匹配: ``` [a-zA-Z][a-zA-Z0-9]* {yylval.id = strdup(yytext); return IDENTIFIER;} ``` 3.编写测试程序。 在本实验中,我们编写一个简单的测试程序,用于测试词法分析器是否正确。 ```c %{ #include "lex.yy.h" %} %option noyywrap %{ int yylex(); void yyerror(char *); %} %union { int num; float fnum; char *id; } %token IF ELSE FOR WHILE DO BREAK CONTINUE RETURN %token INT FLOAT %token ADD SUB MUL DIV MOD %token ASSIGN GT GE LT LE NE EQ %token SEMICOLON COMMA %token LPAREN RPAREN LBRACE RBRACE %token IDENTIFIER %% {if} {printf("IF\n");} {else} {printf("ELSE\n");} {for} {printf("FOR\n");} {while} {printf("WHILE\n");} {do} {printf("DO\n");} {break} {printf("BREAK\n");} {continue} {printf("CONTINUE\n");} {return} {printf("RETURN\n");} [0-9]+ {yylval.num = atoi(yytext); printf("INT %d\n", yylval.num);} [0-9]+"."[0-9]+ {yylval.fnum = atof(yytext); printf("FLOAT %f\n", yylval.fnum);} "+" {printf("ADD\n");} "-" {printf("SUB\n");} "*" {printf("MUL\n");} "/" {printf("DIV\n");} "%" {printf("MOD\n");} "=" {printf("ASSIGN\n");} ">" {printf("GT\n");} ">=" {printf("GE\n");} "<" {printf("LT\n");} "<=" {printf("LE\n");} "!=" {printf("NE\n");} "==" {printf("EQ\n");} ";" {printf("SEMICOLON\n");} "," {printf("COMMA\n");} "(" {printf("LPAREN\n");} ")" {printf("RPAREN\n");} "{" {printf("LBRACE\n");} "}" {printf("RBRACE\n");} [a-zA-Z][a-zA-Z0-9]* {yylval.id = strdup(yytext); printf("IDENTIFIER %s\n", yylval.id);} [ \t\n]+ { /* skip whitespace */ } %% int main(int argc, char *argv[]) { FILE *yyin = fopen(argv[1], "r"); if (!yyin) { printf("Cannot open input file!\n"); return -1; } yylex(); fclose(yyin); return 0; } void yyerror(char *s) { printf("%s\n", s); } ``` 4.使用Flex工具生成词法分析器。 可以使用以下命令生成词法分析器: ``` flex lexer.l ``` 该命令将生成一个名为lex.yy.c的文件,即词法分析器。 5.编译并运行测试程序。 可以使用以下命令编译测试程序: ``` gcc -o lexer lex.yy.c -lfl ``` 该命令将生成一个名为lexer的可执行文件。 可以使用以下命令运行测试程序: ``` ./lexer test.c ``` 其中,test.c是一个待分析的C程序。 实验结果: 假设我们有一个名为test.c的C程序,内容如下: ```c #include <stdio.h> int main() { int a = 10; float b = 3.14; if (a > 5) { printf("a is greater than 5\n"); } else { printf("a is less than or equal to 5\n"); } return 0; } ``` 使用词法分析器对该程序进行分析,输出如下: ``` #include <stdio.h> IDENTIFIER printf LPAREN STRING "a is greater than 5\n" RPAREN SEMICOLON INT IDENTIFIER main LPAREN RPAREN LBRACE INT IDENTIFIER a ASSIGN INT 10 SEMICOLON FLOAT IDENTIFIER b ASSIGN FLOAT 3.140000 SEMICOLON IF LPAREN IDENTIFIER a GT INT 5 RPAREN LBRACE IDENTIFIER printf LPAREN STRING "a is greater than 5\n" RPAREN SEMICOLON RBRACE ELSE LBRACE IDENTIFIER printf LPAREN STRING "a is less than or equal to 5\n" RPAREN SEMICOLON RBRACE RETURN INT 0 SEMICOLON RBRACE ``` 可以看到,词法分析器成功地识别出了关键字、标识符、整数、浮点数、运算符和界符等,并正确地输出了结果。 实验总结: 本实验中,我们学习了词法分析程序的基本原理和算法,并使用Flex工具和正则表达式编写了一个简单的词法分析器。词法分析器能够识别出关键字、标识符、整数、浮点数、运算符和界符等,并对输入的代码进行了正确的分析。通过本实验的学习,我们深入理解了编译原理中的词法分析过程,提高了对编译原理的理解和应用能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

女主对此感到厌烦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值