首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将表达式导出到C,第1部分[wolfram-mathematica]

将表达式导出到C,第1部分[wolfram-mathematica]
EN

Stack Overflow用户
提问于 2011-03-25 22:31:07
回答 1查看 2.5K关注 0票数 14

我在Mathematica中生成了几个表达式,希望将它们导出到外部C程序的源代码中。除了求幂被表示为对Power()的调用之外,"CForm“几乎做了我想要做的事情。我的表达式只涉及很小的幂,所以我更喜欢C中的表达式使用内联乘法,而不是调用Power()

例如,CForm[2 hgt^2 k1inv^3 mx0 wid^2 + hgt^2 k1inv^3 wid^3]会产生

2*Power(hgt,2)*Power(k1inv,3)*mx0*Power(wid,2) + Power(hgt,2)*Power(k1inv,3)*Power(wid,3)

..whereas我想要生成的是:

2*hgt*hgt*k1inv*k1inv*k1inv*mx0*wid*wid + hgt*hgt*k1inv*k1inv*k1inv*wid*wid*wid

我最初试图找出表达式的内部Power[..]部分,并使用x_Symbol^y_Integer /; y > 1 :> Fold[Times, 1, Table[#1, {#2}]]将其重新映射为乘法,但由于mathematica立即将我精心生成的子表达式a*a*a转换回Power[a,3]而受到阻碍;-)我知道它只是想要帮助,但我不知道如何让它停止,在这种情况下...

在我写这个问题的时候,我突然想到,我可以将CForm的输出捕获到一个字符串中,然后对其执行字符串模式匹配和操作,但这是一个好方法吗?我想我更喜欢把它作为一个数学表达式来处理,就像我重新映射然后输出一样。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-03-25 23:03:19

对于手头的案例,您可以使用类似以下内容:

代码语言:javascript
复制
Clear[getCFormNoPowers];
getCFormNoPowers[expr_] :=
  Module[{times},      
   Apply[Function[code, Hold[CForm[code]], HoldAll],
     Hold[#] &[expr /. x_Symbol^y_Integer /; y > 1 :> 
         times @@ Table[x, {y}]] /. times -> Times]];

例如,

代码语言:javascript
复制
In[52]:= getCFormNoPowers[2 hgt^2 k1inv^3 mx0 wid^2+hgt^2 k1inv^3 wid^3]

Out[52]= Hold[2*mx0*(hgt*hgt)*(wid*wid)*(k1inv*k1inv*k1inv) + 
hgt*hgt*(k1inv*k1inv*k1inv)* (wid*wid*wid)]

结果被包装在Hold中,以防止其求值返回到Power-s。您可以随时使用类似于ToString[HoldForm@@result]的内容将其转换为字符串。或者你可以更进一步的操纵。

编辑:

作为另一种选择,您可以这样做:

代码语言:javascript
复制
Clear[getCFormNoPowers];
getCFormNoPowers[expr_] :=
 Block[{Times},
   SetAttributes[Times, {Flat, OneIdentity}];
   Apply[Function[code, Hold[CForm[code]], HoldAll],
   Hold[#] &[expr /. x_Symbol^y_Integer /; y > 1 :> Times @@ Table[x, {y}]]]];

这也将保持您的术语的原始顺序,并将删除不必要的括号,因此这一项似乎完全符合您的规范。

通常,您可能希望了解一下版本8的新的“符号C生成”功能。将代码映射到符号C表达式可能是一种更健壮的方法。通过这种方式,您不必一直担心计算问题,并且最终可以使用新功能来生成整个C程序。

编辑2:

要说明如何使用SymbolicC解决此问题:

代码语言:javascript
复制
Needs["SymbolicC`"];

Clear[getCFormNoPowersSymC];
getCFormNoPowersSymC[expr_] :=
  Block[{Times},
   SetAttributes[Times, {Flat, Orderless}];
   ToCCodeString[
     expr /. x_Symbol^y_Integer /; y > 1 :> Times @@ Table[x, {y}] //.     
       HoldPattern[(op : (Times | Plus))[args__]] :>  COperator[op, {args}]]];

In[53]:= getCFormNoPowersSymC[2 hgt^2 k1inv^3 mx0 wid^2+hgt^2 k1inv^3 wid^3]

Out[53]= 2 * hgt * hgt * k1inv * k1inv * k1inv * mx0 * wid * wid + 
    hgt * hgt * k1inv * k1inv * k1inv * wid * wid * wid

这种方法IMO有几个优点。也许两个主要的问题是可组合性(可以将这些表达式嵌套在它们的符号形式中,从较小的表达式构建更大的代码块),以及不需要过多考虑计算的事实(这里我不需要使用Hold的任何技巧)。

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5433817

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档