2009-10-06 117 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]