我有一些在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)

..而我想生成的是:

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的输出捕获到一个字符串中,然后对其进行字符串模式匹配和操作,但这是一个好方法吗?我想我更喜欢将其作为Mathematica表达式进行处理,因为我需要重新映射然后输出。

最佳答案

对于当前的情况,您可以使用类似以下的内容:

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]];


例如,

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]之类的字符串。或者您可以进行更进一步的操作。

编辑:

或者,您可以执行以下操作:

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解决问题:

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此处)。

关于wolfram-mathematica - 将表达式导出到C,第1部分[wolfram-mathematica],我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5433817/

10-13 06:11