MaxScript で文字列を数値変換するときの注意
MaxScript で文字列を数値に変換することを考えます。なにを今さら、と思いますか?
私もまさか、こんな罠があるとは知りませんでした。今さら罠を発見したので紹介したいと思います。
基本の文字列→数値変換
s = "123" s as integer -->123 s = "123.4" s as float -->123.4
このように、整数への変換は as integer 、浮動小数点数への変換は as float を使います。
変換できないものを渡すとundefined になります。
s = "abc" s as integer --> undefined
問題点
さてここからが問題です。
s = "t" s as integer -->0 s as float -->0.0
はて?
文字列"t" を as integer するとundefined ではなく0 が戻ってきました。つまり0 に変換できたということになります。
そこで調べてみました。
-- アルファベットの配列を作る alphabets = #("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z") -- その整数変換を試す for c in alphabets do ( format "%: %\n" c (c as integer) format "%: %\n" (toLower c) ((toLower c) as integer) )
すると出力が
A: undefined a: undefined B: undefined b: undefined C: undefined c: undefined D: undefined d: undefined E: undefined e: undefined F: undefined f: 0 G: undefined g: undefined H: undefined h: undefined I: undefined i: undefined J: undefined j: undefined K: undefined k: undefined L: 0 l: undefined M: undefined m: 0 N: undefined n: undefined O: undefined o: undefined P: 0 p: undefined Q: undefined q: undefined R: undefined r: undefined S: undefined s: 0 T: undefined t: 0 U: undefined u: undefined V: undefined v: undefined W: undefined w: undefined X: undefined x: undefined Y: undefined y: undefined Z: undefined z: undefined
つまり大文字のL、P、小文字のf、m、s、t が数値変換できてしまい、0 になるということがわかります。
さらに謎
もう少し実験。
"L" as integer -->0 "LL" as integer -->undefined "LP" as integer -->undefined "ff" as integer -->0 "fm" as integer -->0 "fmst" as integer -->0
どうやら大文字は連結するとundefined で変換できなくなり、小文字は連結しても0 に変換されます。
なぜなんだ?
文字列が数字かどうか識別する
さて、なぜこんな話を紹介しているかというと、皆さん文字列が数字かどうか判別したいときどうしてますか? というところにつながるのです。
function isNumber s = ( return ((s as integer) != undefined) )
こんな感じでチェックしたり、してませんか?
私はしてました。ところが上記の問題により、この関数はバグのもとになります。
isNumber "ttt" --> true
ということになるからです。この問題を踏まえて正しく動作するisNumber を作ると次のようになります。
function isNumber s = ( -- as float が undefined になるものは数字ではない if (s as float) == undefined do return false -- as float がundefined にならない場合はすべての文字が数字かどうか確認する -- "." as float は0.0 なので小数点は許容する local numbers = #("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".") for i=1 to s.count do( if (findItem numbers s[i] == 0) do return false ) return true )
そんな面倒なことをしなくてもPython を使えばいいのでは?
もちろんその通りです。
function isNumber s = ( local py = python.import "__builtin__" try ( -- python でfloat に変換 py.float s return true ) catch ( -- 変換できなければfalse を返す return false ) )
まとめ
- MaxScript の文字列→数値変換は意外な挙動をするので要注意
ディスカッション
コメント一覧
まだ、コメントがありません