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