微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

动态构造用户定义的数学函数以在C ++中进行有效调用?

如何解决动态构造用户定义的数学函数以在C ++中进行有效调用?

一个例子是类似Desmos(但作为桌面应用程序)。该函数用户提供为文本,因此无法在编译时编写。此外,该功能在更改之前可以重复使用数千次。但是,一个真实的例子是,函数可能比desmos更频繁地更改,并且其值也可以更多地使用。

我看到四种编写此代码方法

  1. 每次调用函数时,都会用语法分析用户定义的函数。 (许多函数调用速度很慢)
  2. 构造数学表达式的语法树,以便节点包含指向适当数学运算的函数指针,从而使程序每次调用函数时都可以跳过对文本的解析。对于许多函数调用,此速度应该比#1快,但是它仍然涉及函数指针和树,这增加了间接性,并且不如预编译(并优化)函数那样快。
  3. 使用The Tiny C Compiler之类的东西作为使用libtcc进行动态代码生成的后端,以在将用户函数转换为C代码快速编译用户函数,然后在主程序中使用它。由于该编译器每秒可以在我的计算机上编译大约10,000个非常简单的程序,因此解析新函数应该几乎没有延迟。此外,该编译器为该函数生成机器代码,因此不涉及指针或树,并且优化由TinyCC完成。对于像我这样的中级程序员来说,这种方法更令人生畏。
  4. 编写自己的微型编译器(不是C语言,而是专门为我的问题定制的),几乎可以立即生成机器代码。这项工作可能比#3多20倍,并且在将来的改进方面做不到很多(添加求和运算生成器将需要我为此编写更多的汇编代码)。

在C ++领域中,是否存在比#3更简单,但同等或更有效的方法?我对lambda,模板和标准库没有足够的经验,无法确定是否有某种抽象方法可以轻松有效地编写此代码

即使是一种方法,其速度也比#2快但比#3慢,并且不需要动态代码生成也会带来进步。

这更多是出于知识上的好奇,而不是现实中的问题,这就是为什么我如此关注性能,也是为什么我不使用别人的数学解析库的原因。这也是为什么我不考虑使用可以即时解释这种事情的javascript或python解释器。

解决方法

我认为,按照您的选择2进行操作会很好。除了可能更简单之外,还有一个带有Expr方法的float Expr::eval(std::unordered_map<string,float> vars)类。然后使用VarnameAddleftrightSub,{{1 }}等所有您想要的功能。评估时,只需使用Mult之类的参数传递地图,每个Div对象会将其传递给任何子表达式,然后进行操作。

我认为这会相当快。您认为用户输入的表达式有多复杂?大多数表达式可能不需要超过10到20个函数调用。

它也可以变得更快

如果您要使图形功能(或类似功能)成为对象,并且使操作能够使用值的向量而不是单个标量值,则可以大大加快该过程。 / p>

假设您想用10,000点绘制类似{{"x",3},{"y",4}}的图形,如果您的Expr对象一次只处理单个值,是的,就像x^3 - 6x^2 + 11x - 6,如果您的Expr对象可以采用值数组,例如用~10-15 function calls * 10,000 points = a lot jumping around!调用Expr,那么优化后只会〜10-15个函数调用 C ++。这样可以轻松扩展到更多的点,而且仍然非常快。

,

实际上,生成机器代码并不难,关键在于设计解析器,使解析结果遵循计算顺序。

然后,您基本上将机器代码字符串与诸如“将文字推入堆栈”,“对堆栈的两个最高元素执行二进制运算并将结果推入堆栈”之类的语义连接起来,然后从“堆栈”

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。