我在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的输出捕获到一个字符串中,然后对其执行字符串模式匹配和操作,但这是一个好方法吗?我想我更喜欢把它作为一个数学表达式来处理,就像我重新映射然后输出一样。
发布于 2011-03-25 23:03:19
对于手头的案例,您可以使用类似以下内容:
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的任何技巧)。
https://stackoverflow.com/questions/5433817
复制相似问题