Unexpected behavior: CForm converts rationals to floating numbers
Warning: The conversion below can lead to wrong results in the C-code. Be aware of that.
Since you complain anyway about "Sqrt"
and "Pow"
have you considered writing your own cform
? The real CForm
seems a bit stubborn about the numerical evaluation of rational expressions and with your own version you can cure this too. A very basic hack could look like
cform[Rational[a_, b_]] := "(" <> cform[a] <> "/" <> cform[b] <> ")";
cform[Power[a_, b_]] := "pow(" <> cform[a] <> "," <> cform[b] <> ")";
cform[Sqrt[a_]] := "sqrt(" <> cform[a] <> ")";
cform[Plus[a_, b_]] := "(" <> cform[a] <> " + " <> cform[b] <> ")";
cform[Times[a_, b_]] := "(" <> cform[a] <> " * " <> cform[b] <> ")";
cform[a_?AtomQ] := ToString[a];
and then you go
3/40007 + (2 test)/40007 // cform
(* "((3/40007) + ((2/40007) * test))" *)
or even
Series[Sin[x + y], {x, 0, 3}, {y, 0, 3}] // Normal // cform
(*
(x + (((-1/6) * pow(x,3)) + (((1 + ((-1/2) * pow(x,2))) * y) +
(((((-1/2) * x) + ((1/12) * pow(x,3))) * pow(y,2)) + (((-1/6) +
((1/12) * pow(x,2))) * pow(y,3))))))
*)
Maybe you can upload a larger expression to pastebin.com so that we have a better feeling, what kinds of expressions you try to convert.
Update to your comment
There are at least two thing you could make easier for yourself. First is, that all functions which are real function calls in C too, like cexp
, sqrt
, abs
, ... probably don't need all their own rule, because the only important thing is that the function names are converted. Then the arguments are just supplied separated by a comma in parenthesis. Therefore, you could create a general rule and then you have to provide the conversion of the function name only.
Additionally, for everything unmatched, you probably want to call ToString[...,CForm]
to make it convert at least to something. Here is your version striped of the pow and exp rules and I added 4 rules at the end:
cform[Rational[a_, b_]] := cform[a] <> "/" <> cform[b] <> ".";
cform[Complex[a_, b_]] :=
"(" <> If[cform[a] == "0", "", cform[a]] <> "+" <> cform[b] <> "*I" <>
")"; cform[Times[a_, b_]] :=
"(" <> cform[a] <> ")" <> " * " <> "(" <> cform[b] <> ")";
cform[Plus[a_, b_]] := cform[a] <> " + " <> cform[b];
cform[a_?AtomQ] := ToString[a];
cform[h_[args__]] :=
cform[h] <> "(" <> StringJoin[Riffle[cform /@ {args}, ","]] <> ")";
cform[Power] = "pow";
cform[Exp] = "cexp";
cform[Sqrt] = "sqrt";
cform[allOther_] := ToString[allOther, CForm];