数字の桁数を揃えて文字列に変換したいということは、色々な場面であると思います。
まず、日付など1〜2桁のもので、1桁のものは頭に0を付けたい場合は。以下のように、数値の頭に文字列の"0"を加えて文字列化し、文字列の最後から2キャラクターを取り出すことで、2桁に揃えます。
set theDay to 2
set theDay to text -2 thru -1 of ("0" & theDay)
日付で無い場合は、もう少し桁が多い場合もあるでしょう。例えば8桁までの整数があって、足りない分の桁には"-"を入れたいという場合は、先ほどのスクリプトを応用して、以下のようにします。
set theNum to 10000
set theNum to text -8 thru -1 of ("--------" & theNum)
整数の場合は、先ほどのやり方で問題ありませんが、小数点以下が存在する場合の桁揃えは、もう少し複雑になります。
要は、整数部分と、小数点以下の部分を分離して、それぞれに処理をすればいいのです。以下のハンドラの場合は、整数5桁、小数点以下3桁で処理しています。
numChopper(150.56)
on numChopper(theNum)
set tmp to text item delimiters
set theNum to (theNum as string) & ".0" -- 整数であった場合のために".0"を追加しておく
set text item delimiters to "."
set {theUpper, theDowner} to text items of theNum -- "."で前後に分割
set text item delimiters to tmp
set theUpper to text -5 thru -1 of ("0000" & theUpper)
set theDowner to text 1 thru 3 of (theDowner & "00")
return theUpper & "." & theDowner
end numChopper
上の例では、text item delimitersを利用しましたが、今度はdevとmodを利用して、整数と小数点以下に分けています。
numChopper(150.56)
on numChopper(theNum)
set theUpper to text -5 thru -1 of ("0000" & (theNum div 1))
set theDowner to text 2 thru 4 of ((1 + (theNum mod 1)) * (10 ^ 3) as string)
return theUpper & "." & theDowner
end numChopper
まず、整数部分ですが「theNum div 1」とすることで、小数点以下を無くすことができます。その後は、先ほどと同じ"0"を付け加える処理です。
divを使わずにOSAX命令のroundを使って「round theNum rounding down」としても構いませんが、多少スピードが落ちる上に、書くのが面倒ですから、ここでは無理に使う理由は無いでしょう。詳しくは「数値を丸める」の項を参照して下さい。
次に、小数点以下の部分は「theNum mod 1」で小数点以下を取り出します。
ここで1を加えているのは、その後のかけ算で桁が上がらないと困るので、ダミーとして1を加えているわけです。ダミーなので1でなくても2でも3でも構いません。
さらに値に10^3を掛けることによって、桁を3つ上げます。10^3は1000でもいいのですが、3桁あげるということが分かりやすいように10^3を使っています。
最後に文字列に変換した後、2〜4つめの文字を取り出しています。1つめはダミーなので、飛ばすわけです。
このようにややこしい過程を辿りますが、スクリプトは逆に短くなります。
少なめの数なら問題ありませんが、大きな数になるとAppleScriptは数字を指数表記し始めます。
そうなると今までの方法は使えません。そこで、指数表記をされるような大きな数を文字列に変換します。
real2Str(1.51252E+13)
on real2Str(theNum)
set theNum to theNum as string
if "E" is not in theNum then return theNum -- 指数表記で無い場合は処理しない
-- 単語区切りを利用し 数値E, +, 指数 に分ける
set {x, ope, e} to words of theNum
-- 必ず2つめに小数点が来るので、それを利用し小数点を取り除く
set x to (character 1 of x) & (text 3 thru -2 of x)
-- ゼロを付加する
set zeros to e-(length of x)+1
repeat zeros times
set x to x & "0"
end repeat
return x
end real2Str
逆に極端に小さな値の場合も指数表記になりますので、そちらも処理します。
real2Str(1.51252E-5)
on real2Str(theNum)
set theNum to theNum as string
if "E" is not in theNum then return theNum -- 指数表記で無い場合は処理しない
-- 単語区切りを利用し 数値E, 指数 に分ける
set {x, e} to words of theNum
-- 必ず2つめに小数点が来るので、それを利用し小数点を取り除く
set x to (character 1 of x) & (text 3 thru -2 of x)
-- ゼロを付加する
repeat e - 1 times
set x to "0" & x
end repeat
return "0." & x
end real2Str
指数表記かどうかの判定の後、+か-の符号が含まれていることを確認して場合分けし、上記の二種類の方法を適用し、数値が負であった場合も考慮に入れると、最終的に以下のようなハンドラになりました。
んー、ちょっとことが大袈裟になりすぎたような。もう少し簡単に書けそうな気がする。
real2Str(-1.51252E-8)
on real2Str(theNum)
-- 正負で、以降の処理を同じにするため、符号を記録し、負の場合は正に反転する
if theNum >= 0 then
set ope to ""
else
set ope to "-"
set theNum to -theNum
end if
set theNum to theNum as string
if "E" is not in theNum then return ope & theNum -- 指数表記で無い場合は処理しない
-- "E"を区切りに分割
set tmp to text item delimiters
set text item delimiters to "E"
set {x, e} to text items of theNum
set text item delimiters to tmp
-- 必ず2つめに小数点が来るので、それを利用し小数点を取り除く
set x to (character 1 of x) & (text 3 thru -1 of x)
-- ゼロの数を求めるための前処理
set e to e + 1
if e > 0 then
-- ゼロを付加する(大きい数の場合)
repeat e - (length of x) times
set x to x & "0"
end repeat
else
-- ゼロを付加する(小さい数の場合)
repeat -e times
set x to "0" & x
end repeat
set x to "0." & x
end if
-- 符号を付けて、値を返す
return ope & x
end real2Str
桁が多くなると、適当に区切りを入れた方が見やすいのは常識です。
それを自動化してみましょう。real2strは、先ほど作ったハンドラです。
普通は、正の整数に3桁ごとでしか区切りを入れませんから、それに対応したハンドラにします。特に変則的な処理はしていません。
delimitNum of (real2str(1.51252E+8))
on delimitNum of theStr
set lengthOfStr to length of theStr
set restOfStr to (lengthOfStr mod 3)
-- リストに3区切りで文字列を取り出す
set theList to {}
repeat with i from lengthOfStr to (x + 1) by -3
set beginning of theList to text (i - 2) thru i of theStr
end repeat
-- 3で割り切れずあまった部分を追加
if restOfStr > 0 then set beginning of theList to text 1 thru restOfStr of theStr
-- ","を区切りごとに挿入
set tmp to text item delimiters
set text item delimiters to ","
set theStr to theList as string
set text item delimiters to tmp
return theStr
end delimitNum
これらの桁揃えなどの処理は、AppleScript以外の言語では普通に持っているものなので、どうにか標準で用意して欲しいところです。
見ての通り、たいしたプログラムでは無いので、OSAXではなく本体に実装して欲しいと思います。
とりあえずは、Tanaka's osaxのMT Digit Stringを使えば一撃です。