深入解析eval()函数与表达式转换问题及优化评测数据构造技巧

总体思路如上,这里有更多细节

深入解析eval()函数与表达式转换问题及优化评测数据构造技巧

1.1 关于eval()函数无法将包含前导0的字符串转换为表达式的问题

  1. #去除前导0

  2. str = re.sub(r'(?, "", str)

1.2 关于如果转换后的表达式是常量且被识别为int时,无法通过替换求值的问题。

  1. #直接特判

  2. if isinstance(expr,int):

  3. result = expr

  4. else:

  5. #此处令x=2计算数值进行比较

  6. result = expr.evalf(subs={x: 2})

1.3 关于管道的使用

  1. #只是举个例子,说明.sh编写应有的样子

  2. cat $InputFileName | while read line

  3. do

  4. ...

  5. correctOutput=$(echo "$line" | python diff.py)

  6. result=$(echo "$myOutPut$space$correctOutput" | python compare.py)

  7. ...

  8. done

1.4 sympy的简化方法降低了评估速度。不建议使用1.5关于评估数据的构建(以TaskTwo为例)

由于该任务只有幂函数、sin、cos这三个因素,所以作者选择其中的任意一两个,包括三个7模式来生成测试数据,并将几组指标分别设置为0。 1、-1数据(即将[0-9]全部替换为[0-1])

一些常规规则如下:

  1. regex1 = "[+-][0-9](\\*x(\\*\\*[+-]?[0-9])?)*"

  2. regex2 = "[+-][0-9](\\*sin\\(x\\)(\\*\\*[+-]?[0-9])?)*"

  3. regex6 = "([+-][2-9])\\*sin\\(x\\)(\\*\\*[+-]?[2-9])?\\*cos\\(x\\)(\\*\\*[+-]?[2-9])?"

  4. regex7 = "[+-][0-9]\\*x(\\*\\*[+-]?[0-9])?\\*[0-9]{1,2}\\*sin\\(x\\)(\\*\\*[+-]?[0-9])?"

  5. regex10 = "[+-][0-1]{2,3}(\\*x(\\*\\*[+-]?[0-1])?)+(\\*sin\\(x\\)(\\*\\*[+-]?[0-9])?)+"

由于本次测试的测试数据最多不超过100个字符,因此建议将常数因子设置为个位数。

2.使用Junit

作者:乔盛业

  1. //只是举个例子,Junit的组件还是很多的

  2. import org.junit.Test;

  3. import JUnitTestTools.EnhancedUserTestTools;

  4. import java.io.File;


  5. public class PolyTest {


  6. @Test

  7. public void main() throws Exception {

  8. new EnhancedUserTestTools(Poly.class, 2000).testAll(new File("./test/poly/test1.txt"));

  9. }

  10. }

3.使用子流程

作者:冯天宇

3.1 关于subprocess的使用

我们可以通过调用 subprocess.Popen() 来运行我们的 java 程序。 Popen()提供stdin、stdout等参数。我们可以轻松地将输入和输出重定向到python中的文件对象,或者子进程。 PIPE,直接使用write()、readlines()等方法输入并获取输出。

让我们看一个例子:

  1. from subprocess import Popen, PIPE


  2. p = Popen(r'echo hahaha', stdout = PIPE, shell = True, text=True)

  3. print(p.stdout.readline())

运行结果为:

  1. hahaha

在本例中,我们将输出重定向到 PIPE,然后通过 PIPE 的 readline() 方法读取输出。 text=True参数可以帮助我们将PIPE的输入输出从字节流转换为str类型,以方便数据处理。

同样,如果输入被重定向到PIPE(stdin=PIPE),那么就可以通过p.stdin.write(str)向程序输入数据

3.2 测试流程

整体测试流程大致分为三个部分:测试用例生成、程序执行、运行结果验证。

在测试用例生成部分,我们使用xeger直接生成大量随机数据;

在执行程序部分,我们通过Popen调用Java程序;

在结果验证部分,我们使用sympy对原始表达式进行微分,并将导数结果与程序进行比较。

总体程序框架如下:

  1. import ...

  2. from ... import ...


  3. caseSize = 100

  4. cases = case_gen(caseSize, ...)#input list

  5. p = Popen(r'java -classpath ',

  6. stdin = PIPE, stdout = PIPE, shell = True, text=True)

  7. for case in cases:

  8. p.stdin.write(case)

  9. out = p.stdout.readlines()#output list

  10. ans = calcAns(cases)#answer list

  11. for i in range(caseSize):

  12. if (!equal(out[i],ans[i])):

  13. print("")

一些建议: 1、只有了解昂神团队对OO的改革,才能知道17级及以上会计专业学生面临的OO体系的合理性。

2、作为贝主任的学生,怎么能错过ljz学长的精彩博客呢?

比如这个新手教程:

3、阿里巴巴团队推出的优秀开发工具:Arthas

相信我,任何 API 都比你的打印更好

4.接口适配器4.1问题介绍:

有时我们编写一个包含多个方法的接口。当我们编写接口的实现类时,必须实现接口中的所有方法。有时这是浪费,因为并非所有方法都是我们需要的。有时只需要一些。 (不考虑接口中的方法可以删除到所有实现类的重写方法的情况,不需要重写多余的方法)

4.2 问题解决:

使用接口的适配器:借助抽象类,抽象类实现接口和所有方法。那么我们就不再和原来的接口打交道了,而只接触抽象类,也就是继承抽象类,然后再重写我们需要的方法

4.3 问题扩展:

上面提到的抽象类还可以提取实现类的公共方法,以简化代码逻辑和数量。

5.理论与实践相结合的经典书籍:6.hdl的随机三角函数化简方法(针对TaskTwo)

一些神秘的简化方法也能达到意想不到的效果,比如hdl使用的蒙特卡罗方法

你可能想看:
« 上一篇
下一篇 »

相关推荐

java中什么是冒泡,冒泡算法

2026年09月06日

27阅读

java中冒号,java双冒号

2026年09月06日

26阅读

java中的->,java中的是什么意思

2026年09月06日

24阅读

java中的super用法,Java中super的说明

2026年09月06日

28阅读

java中反射的应用,java中反射的应用场景

2026年09月06日

26阅读

java中开关的定义,Java关键字有哪些

2026年09月06日

26阅读