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

标签 wolfram-mathematica

我有几个在 Mathematica 中生成的表达式,我想将它们导出到外部 C 程序的源代码中。 “CForm”几乎可以满足我的要求,只是求幂表示为对 Power() 的调用。 .我的表达式只涉及小幂,所以我更喜欢 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/

相关文章:

Mathematica 中另一个 Dynamic 中的动态列表选择

wolfram-mathematica - 纹理球体基元

matlab - 如何绘制 DNA 序列的基因图,比如 ATGCCGCTGCGC?

matrix - 在Mathematica中将坐标系转换为矩阵

wolfram-mathematica - Mathematica积分评估只是显示为格式正确的文本?

windows - 运行 NDSolve 时内存耗尽

wolfram-mathematica - 如何获取(不显示)节号

list - 数学 : Determine if all integers in a list are less than a number?

wolfram-mathematica - 如何在 Mathematica 函数中禁用区分大小写?

regex - Mathematica中的错误: regular expression applied to very long string