2009-10-06 99 views
25

我不知道为什么维基百科lists Mathematica as a programming language with printf。我只是无法在Mathematica中找到等价物。Mathematica中的Sprintf等价物?

我的具体任务是处理数据文件带衬垫的数字,我用

fn=$(printf "filename_%05d" $n) 

做在bash我的数学发现的最接近的功能是PaddedForm的列表。而且一些试验和错误之后,我

"filename_" <> PaddedForm[ [email protected]#, 4, NumberPadding -> {"0", ""} ]& 

这是非常奇怪的是,我必须使用4号拿到相似,我从“%05D”得到的结果得到了它。我根本不理解这种行为。有人可以向我解释吗?

这是实现我在bash中用过的最好方法吗?

+0

这是奇怪的 - 我从来没有意识到在Mathematica printf等价物。我以前使用过很多PaddedForm(以及各种精确控制)的东西。我也盯着PaddedForm文档,试图弄清楚这个额外的填充字符。 +1。我想知道。 – Cascabel 2009-10-06 16:34:26

+1

我的理论是维基百科将Mathematica列为带有printf的语言,因为它具有StringForm。但是StringForm是printf的悲伤,苍白的阴影。 – Pillsy 2009-10-06 17:02:42

+0

['IntegerString'](http://reference.wolfram.com/language/ref/IntegerString.html) – yohai 2014-10-21 20:54:52

回答

9

我不会为此使用PaddedForm。事实上,我不确定PaddedForm对任何事情都有好处。相反,我会用好老ToStringCharactersPadLeft,像这样:

toFixedWidth[n_Integer, width_Integer] := 
    StringJoin[PadLeft[Characters[ToString[n]], width, "0"]] 

然后你可以使用StringFormToString,使您的文件名:

toNumberedFileName[n_Integer] := 
    [email protected]["filename_``", toFixedWidth[n, 5]] 

数学是不是很适合到这种类型的线路。

编辑补充:适当的数学不具备所需的功能,但java.lang.String类有静态方法format()这需要printf风格的参数。您可以轻松地使用Mathematica的JLink功能调用它。性能将不会很好,但是对于很多使用情况下,你就不会想那么多:

Needs["JLink`"]; 
LoadJavaClass["java.lang.String"]; 
LoadJavaClass["java.util.Locale"]; 
sprintf[fmt_, args___] := 
String`format[Locale`ENGLISH,fmt, 
    MakeJavaObject /@ 
    Replace[{args}, 
    {x_?NumericQ :> [email protected], 
    x : (_Real | _Integer | True | 
     False | _String | _?JavaObjectQ) :> x, 
    x_ :> MakeJavaExpr[x]}, 
    {1}]] 

你需要做一些更多的工作,因为JLINK有点哑有关使用Java功能可变数量的参数。 format()方法采用格式字符串和Java Object的数组,Mathematica不会自动执行转换,这就是MakeJavaObject的用途。

+0

这对于一个简单的printf函数来说确实非常复杂。 – jxy 2009-10-06 19:02:10

+0

有微小的bug:“w”而不是“宽度”。 – dreeves 2010-04-18 14:26:12

+0

感谢您的Java功能。它看起来像我们可以拥有的最好的。 – jxy 2010-08-06 21:49:43

1

我同意Pillsy。 下面是我将如何做到这一点。 请注意便利的cat函数,我认为它有点像sprintf(不包括像StringForm提供的占位符),因为它的工作方式与Print相同(可以打印任何表达式连接而不转换为String),但生成一个字符串而不是发送标准输出。

cat = [email protected]@(ToString/@{##})&; 

pad[x_, n_] := If[[email protected][x]>=n, cat[x], 
              [email protected]@PadLeft[[email protected][x],n,"0"]] 

cat["filename_", pad[#, 5]]& 

这很像Pillsy的答案,但我认为cat使得它干净了一点。 另外,我认为在pad功能中有条件更安全 - 最好是填充错误,而不是数字错误。

5

你也可以定义为前面提到的这传递所有参数,以StringForm []和使用IntegerString或填充功能的函数:

Sprintf[args__] := StringForm[args__] // ToString; 
file = Sprintf["filename_``", IntegerString[n, 10, 5]]; 
8

我碰到了同样的问题相当多,并决定编写我自己的功能。我没有用Java做它,而是在Mathematica中使用字符串操作。结果很长,因为我实际上也需要%f的功能,但它起作用,现在我把它作为一个可以随时使用的包。这里有一个链接到GitHub的项目:

https://github.com/vlsd/MathPrintF

它配备了安装说明(实际上只是复制目录某处在$ PATH)。

希望这会对至少有一些帮助。

2

IntegerString完全符合您的需求。在这种情况下,它将是

IntegerString[x,10,5]