2009-10-27 107 views
2

假设我需要一个函数,它接收一个数字并将其作为字符串返回,完全按照给出的。以下不工作:可以区分foo [.2]和foo的Mathematica函数foo [.20]

SetAttributes[foo, HoldAllComplete]; 
foo[x_] := ToString[[email protected]] 

的输出foo[.2]foo[.20]是相同的。

我想这样做的原因是我想要一个能够理解带点作为分隔符的日期的函数,例如f[2009.10.20]。我意识到这是对Mathematica的一种奇怪的滥用,但是我正在制作一个领域特定的语言,并且想通过仅仅执行一个eval(ToExpression)来使用Mathematica作为解析器。如果我可以依靠两位数的日期和月份(如2009.01.02),但我希望允许2009.1.2,并且最终导致上述问题,我实际上可以完成这项工作。

我怀疑唯一的答案是将该东西作为一个字符串传递,然后解析它,但也许有一些我不知道的技巧。请注意,这与这个问题有关:Mathematica: Unevaluated vs Defer vs Hold vs HoldForm vs HoldAllComplete vs etc etc

回答

6

我不会依赖Mathematica的float解析。相反,我会在MakeExpression上为foo定义规则。这允许您在输入框中截取输入,然后将其解析为浮点数。这对规则应该是一个很好的起点,至少StandardForm

MakeExpression[RowBox[{"foo", "[", dateString_, "]"}], StandardForm] := 
    With[{args = Sequence @@ Riffle[StringSplit[dateString, "."], ","]}, 
    MakeExpression[RowBox[{"foo", "[", "{", args, "}", "]"}], StandardForm]] 

MakeExpression[RowBox[{"foo", "[", RowBox[{yearMonth_, day_}], "]"}], 
    StandardForm] := 
    With[{args = 
    Sequence @@ Riffle[Append[StringSplit[yearMonth, "."], day], ","]}, 
     MakeExpression[RowBox[{"foo", "[", "{", args, "}", "]"}], StandardForm]] 

我需要第二个规则,因为笔记本的接口将“很有帮助”插入空格,如果你尝试将小数点后第二位在数。

编辑:为了使用这个从内核,你需要使用前端,但是这往往在7版本很容易。如果你能得到你的表达作为一个字符串,结合使用UsingFrontEndToExpression

UsingFrontEnd[ToExpression["foo[2009.09.20]", StandardForm] 

编辑2:有很多的可能性,如果你想与$PreRead玩,它允许你将特殊处理适用于作为字符串输入,,他们在解析之前。

+0

神圣的废话,你真了不起!我曾认为这是不可能的。一个问题:我没有使用前端,而是内核处理的纯文本。在那种情况下,你认为我毕竟运气不好? (我很快就会尝试更多的自己,这是一个很好的领导,非常感谢!) – dreeves 2009-10-27 16:09:08

1

浮点数,IIRC,由Mathematica分解成实际的浮点数,所以没有真正的方法去做你想要的。

+0

数学太灵活了国家“没有真正的方法”。你应该删除这个答案。 – 2011-01-11 16:45:13

3
$PreRead = If[$FrontEnd =!= Null, #1, 
StringReplace[#,x:NumberString /; StringMatchQ[x,"*.*0"] :> 
    StringJoin[x, "`", ToString[ 
     StringLength[StringReplace[x, "-" -> ""]] - 
     Switch[StringTake[StringReplace[x, 
      "-" -> ""], 1], "0", 2, ".", 1, _, 
     1]]]]] & ; 

将显示foo [.20]为foo [0.20]。它的InputForm将 富[0.2`2]

我发现,解析和显示数学数字格式比 它应该是更加困难......

相关问题