在 C 代码中使用 bc
Using bc from C code
我正在使用 lex 和 yacc 编写表达式求值器的代码,它可以进行以下操作:
/ , * , + , - , pow(a,b) , sqrt(a) , log(a)
表达式中也可以有括号
输入表达式在文件中"calculator.input"
我必须将我的代码时间与 bc 进行比较,我面临以下问题:
1) bc 不接受 pow(a,b) 和 log(a) 而是接受 a^b 和 l(a) 。
我该如何更改?
2) 如何在 yacc 程序的主要功能中使用 bc?或者无法完成?
我认为更改代码比更改 bc
更容易,但如果您想尝试,可以在 [=39] 上找到指向 bc
源代码包的指针=].当然,最终结果严格来说不再是 bc
,所以我不知道它是否仍然算作您的作业。
我不知道你应该实现的 pow
函数的规范是什么,但请注意 bc
的 ^
运算符只允许整数指数,所以它可能不适用于您的所有测试用例(当然,除非您所有的测试用例都有整数指数。)您可以使用 e(l(a)*b)
计算 a^b
,但对于整数指数它不会那么准确:
e(l(10)*100)
99999999999999999920085453156357924020916787698393558126052191252537\
96016108317256511712576426623511.11829711443225035170
10^100
10000000000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000
您可能想咨询您的导师、教授或助教。
如果您不想(或不允许)手动生成 bc
等效测试用例,您可以使用 sed
(如果指数sub-expressions 并不复杂),或者调整计算器以输出 bc
语法中的表达式。后者将是一个相当简单的项目,您可能会通过实施它学到一些东西。
如果您使用的是 Unix-like 系统,您可以轻松地 运行 来自 C 程序的任何 command-line 实用程序。 (事实上 ,您也可以在非 Unix-like 系统上执行此操作,但库函数会有所不同。)如果您不需要通过其 stdin
将数据传递给 bc
,您可以使用 popen(3)
库函数,这当然是最简单的解决方案。
否则,你必须设置一对pipe(2)
s (one for writing to bc
's stdin
and the other for reading from its stdout
), fork(2)
a child process, and use one of the exec*
function calls, probably execlp(3)
or execvp(3)
, to run bc
in the child. (Watch out for pipe deadlock while you are writing to and reading from the child.) Once the child process finishes (which you'll notice because you'll get an EOF on the pipe you're using to read from its stdout
, you should use wait(3)
或waitpid(3)
才能得到它的状态码。
如果这一切看起来太复杂,您可以使用更简单的解决方案,即 运行 将您的程序和 shell 中的 bc
结合起来。 (您可以在 Unix-like shell 上使用 time
shell built-in 来衡量执行时间,尽管它不会是微秒分辨率,这可能是如此简单的程序所必需的。)
我正在使用 lex 和 yacc 编写表达式求值器的代码,它可以进行以下操作:
/ , * , + , - , pow(a,b) , sqrt(a) , log(a)
表达式中也可以有括号
输入表达式在文件中"calculator.input"
我必须将我的代码时间与 bc 进行比较,我面临以下问题:
1) bc 不接受 pow(a,b) 和 log(a) 而是接受 a^b 和 l(a) 。 我该如何更改?
2) 如何在 yacc 程序的主要功能中使用 bc?或者无法完成?
我认为更改代码比更改 bc
更容易,但如果您想尝试,可以在 [=39] 上找到指向 bc
源代码包的指针=].当然,最终结果严格来说不再是 bc
,所以我不知道它是否仍然算作您的作业。
我不知道你应该实现的 pow
函数的规范是什么,但请注意 bc
的 ^
运算符只允许整数指数,所以它可能不适用于您的所有测试用例(当然,除非您所有的测试用例都有整数指数。)您可以使用 e(l(a)*b)
计算 a^b
,但对于整数指数它不会那么准确:
e(l(10)*100)
99999999999999999920085453156357924020916787698393558126052191252537\
96016108317256511712576426623511.11829711443225035170
10^100
10000000000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000
您可能想咨询您的导师、教授或助教。
如果您不想(或不允许)手动生成 bc
等效测试用例,您可以使用 sed
(如果指数sub-expressions 并不复杂),或者调整计算器以输出 bc
语法中的表达式。后者将是一个相当简单的项目,您可能会通过实施它学到一些东西。
如果您使用的是 Unix-like 系统,您可以轻松地 运行 来自 C 程序的任何 command-line 实用程序。 (事实上 ,您也可以在非 Unix-like 系统上执行此操作,但库函数会有所不同。)如果您不需要通过其 stdin
将数据传递给 bc
,您可以使用 popen(3)
库函数,这当然是最简单的解决方案。
否则,你必须设置一对pipe(2)
s (one for writing to bc
's stdin
and the other for reading from its stdout
), fork(2)
a child process, and use one of the exec*
function calls, probably execlp(3)
or execvp(3)
, to run bc
in the child. (Watch out for pipe deadlock while you are writing to and reading from the child.) Once the child process finishes (which you'll notice because you'll get an EOF on the pipe you're using to read from its stdout
, you should use wait(3)
或waitpid(3)
才能得到它的状态码。
如果这一切看起来太复杂,您可以使用更简单的解决方案,即 运行 将您的程序和 shell 中的 bc
结合起来。 (您可以在 Unix-like shell 上使用 time
shell built-in 来衡量执行时间,尽管它不会是微秒分辨率,这可能是如此简单的程序所必需的。)