データ型

IDLは強い動的型付け言語である。変数の型は、変数に値が代入された時点で決まる。

IDLのデータ型一覧

COMPLEX, 構造体, DCOMPLEX, POINTER, オブジェクト, LIST, HASHは複合型である。Type Codeは0~15の整数である。Type Code と Type NameはSIZE関数などさまざまな関数で用いられる。

Type Code Type Name データ型 値の範囲 作成方法 型変換関数 配列作成関数
0 UNDEFINED 変数が未定義であることを示す。!NULL a = !NULL, a = [], a = {}
1 BYTE 8bit符号なし整数 0~255 a = 1B BYTE BYTARR
2 INT 16bit符号付き整数 -32768~32767 a = 1, a = 1S [注3] FIX INTARR
3 LONG 32bit符号付き整数 -231~231-1 a = 1L LONG LONARR
4 FLOAT 32bit単精度浮動小数点数 (有効数字約6~7桁) ±(1.175e-38~3.403e+38) a = 1.0, a = 1.0E [注4] FLOAT FLTARR
5 DOUBLE 64bit倍精度浮動小数点数 (有効数字約14桁) ±(2.225e-308~1.798e+308) a = 1.0D DOUBLE DBLARR
6 COMPLEX 複素数 (単精度浮動小数点数) 実部・虚部ともにFLOATに同じ a = COMPLEX(1.0, 1.0) または a = 1 + 1i [注5] COMPLEX COMPLEXARR
7 STRING 可変長文字列 2 GiB (231-1 B)まで a = 'abc' STRING STRARR
8 構造体名(無名構造体のときはANONYMOUS) (構造体の配列はSTRUCT) [注1] 構造体 a = {name, tag: 0} または CREATE_STRUCT関数
9 DCOMPLEX 複素数 (倍精度浮動小数点数) 実部・虚部ともにDOUBLEに同じ a = DCOMPLEX(1.0, 1.0) または a = 1d + 1di [注5] DCOMPLEX DCOMPLEXARR
10 POINTER ポインタ PTR_NEW関数 PTRARR
11 クラス名 (nullオブジェクトまたはオブジェクトの配列のときOBJREF) [注2] オブジェクト OBJ_NEW関数 OBJARR
11 LIST (配列にするとOBJREF) [注2] リスト (IDL8以降) LIST関数
11 HASH (配列にするとOBJREF) [注2] ハッシュ (IDL8以降) HASH関数
11 ORDEREDHASH (配列にするとOBJREF) [注2] 順序つきハッシュ (IDL8.3以降) ORDEREDHASH関数
11 DICTIONARY (配列にするとOBJREF) [注2] キーの大文字・小文字を区別しないハッシュ (IDL8.3以降) DICTIONARY関数
11 BIGINTEGER (配列にするとOBJREF) [注2] 多倍長整数 (IDL8.4以降) a = BigInteger(100) または a = BigInteger('123456789012345678980') BigInteger
12 UINT 16bit符号なし整数 0~65535 a = 1U, a = 1US [注3] UINT UINTARR
13 ULONG 32bit符号なし整数 0~232-1 a = 1UL ULONG ULONARR
14 LONG64 64bit符号付き整数 -263~263-1 a = 1LL LONG64 LON64ARR
15 ULONG64 64bit符号なし整数 0~264-1 a = 1ULL ULONG64 ULON64ARR

データ型を判定する

a の型を調べるにはSIZE関数を使う。/TYPE キーワードを指定すると Type Codeを、/TNAMEキーワードを指定するとType Nameを返す。IDL 8.0 以降では TYPENAME関数も使える。構造体やオブジェクトの場合、SIZE(/TNAME)とTYPENAMEの結果が異なる場合があるのに注意。IDL 8.4 以降ではVariable Attributesも使える。

IDL> a = 1ULL
IDL> PRINT, SIZE(a, /TYPE)
15
IDL> PRINT, a.typecode ; IDL 8.4以降
15
IDL> PRINT, SIZE(a, /TNAME)
ULONG64
IDL> PRINT, TYPENAME(a) ; IDL 8.0 以降
ULONG64
IDL> PRINT, a.typename ; IDL 8.4 以降
ULONG64

IDL 8.0 で、データ型を判定するISA関数が追加された。以下、ISA関数を使う場合と、従来の方法を併記する。

変数 a がFLOAT型であるかどうかを判定する。

IDL> a = 1.0
IDL> PRINT, ISA(a, 'FLOAT')
1
IDL> PRINT, SIZE(a, /TNAME) eq 'FLOAT'
1

変数 a が数値(整数、小数、複素数)であるかどうかを判定する。

IDL> a = 1
IDL> PRINT, ISA(a, /NUMBER)
1
IDL> PRINT, ([0b, 1b, 1b, 1b, 1b, 1b, 1b, 0b, 1b, 1b, 0b, 0b, 1b, 1b, 1b, 1b])[SIZE(a, /TYPE)]
1

変数 a が配列(長さ1の配列も配列である)であるかどうかを判定する。(これとは逆の /SCALAR キーワードもある)

IDL> a = [1, 2, 3]
IDL> PRINT, ISA(a, /ARRAY)
1
IDL> PRINT, SIZE(a, /DIMENSIONS) NE 0
1
IDL> PRINT, a.ndim NE 0 ; IDL 8.4 以降
1

データ型を変換する

数値・文字列型間で相互に型変換する関数が用意されている(上の表の型変換関数の列)。たとえば、FLOAT関数は、他のデータ型の値をFLOAT型に変換する。FIX関数だけは特別で、TYPEキーワードでType Codeを指定することにより、1つの関数で任意の型に変換できる。IDL 8.4以降では IDL_Variable::Convert メソッドを用いることもできる。これらの変換関数は、スカラー変数だけではなく配列にも対応している。

IDL> HELP, FLOAT(1)
<Expression> FLOAT = 1.00000
IDL> HELP, FIX(1, TYPE = 4)
<Expression> FLOAT = 1.00000
IDL> HELP, UINT(3.5)
<Expression> UINT = 3
IDL> HELP, FIX(3.5, TYPE = 12)
<Expression> UINT = 3
IDL> HELP, (1).Convert(/FLOAT) ; IDL 8.4 以降
<Expression> FLOAT = 1.00000

複素数から実数への変換を行うと、実部のみになる。

IDL> HELP, COMPLEX(1, 2)
<Expression> COMPLEX = ( 1.00000, 2.00000)
IDL> HELP, FLOAT(COMPLEX(1, 2))
<Expression> FLOAT = 1.00000

複素数から実部のみを取り出す関数 REAL_PART、虚部のみを取り出す関数 IMAGINARY もあり、こちらを使うと単精度/倍精度は保存される。

STRING関数で数値から文字列へ変換する場合、デフォルトでは元の型の最大桁数に対応した桁数が確保されるため、先頭に空白がつく。出力の書式を変更するにはFORMATキーワードを指定する。

IDL> HELP, STRING(3)
<Expression> STRING = ' 3.14000'

IDL> ; IDL 8.6以降ではC言語風のフォーマット指定子も利用できる
IDL> HELP, STRING(3.14, FORMAT='%10.3e')
<Expression> STRING = ' 3.140e+00'

IDL> ; %gを用いると、小数点以下の余分な0が省略される
IDL> HELP, STRING(3.14, FORMAT='%g')
<Expression> STRING = '3.14'

IDL> ; 以下、従来のFORTRAN風のフォーマット指定子
IDL> HELP, STRING(3, FORMAT='(i3)')
<Expression> STRING = ' 3'
IDL> HELP, STRING(3, FORMAT='(i0)')
<Expression> STRING = '3'
IDL> HELP, STRING(3, FORMAT='(i03)')
<Expression> STRING = '003'
IDL> HELP, STRING(3.14, FORMAT='(f)')
<Expression> STRING = ' 3.1400001'
IDL> HELP, STRING(3.14, FORMAT='(f10.3)')
<Expression> STRING = ' 3.140'
IDL> HELP, STRING(3.14, FORMAT='(f0.3)')
<Expression> STRING = '3.140'
IDL> HELP, STRING(3.14, FORMAT='(e)')
<Expression> STRING = ' 3.1400001e+00'
IDL> HELP, STRING(3.14, FORMAT='(e10.3)')
<Expression> STRING = ' 3.140e+00'

文字列から数値への変換も可能である。文字列の先頭から、数値として解釈できる範囲で数値に変換する。数値として解釈不能な場合は、Warningが出力され0が返る。このWarningをプログラムで検出したい場合はON_IOERRORプロシージャを使う。

IDL> HELP, FLOAT('1.5e-5')
<Expression> FLOAT =1.50000e-05
IDL> HELP, FLOAT('1.5e-5ABCDEFG')
<Expression> FLOAT = 1.50000e-05
IDL> HELP, FLOAT('ABCDEFG1.5e-5')
% Type conversion error: Unable to convert given STRING to Float.
% Detected at: $MAIN$
<Expression> FLOAT = 0.00000

BYTE型と文字列の相互変換については特別な処理が行われるので注意が必要である。STRING関数でBYTE型の数値を文字列に変換する場合、数値はASCIIコードだとみなされ、対応する文字に置き換わる。これを防ぐには /PRINT キーワードを指定するか、FORMATキーワードで書式を指定する。またはINTEGER型等の他の型に一旦変換してからSTRINGに渡す。

IDL> HELP, STRING(97B)
<Expression> STRING = 'a'
IDL> HELP, STRING(97B, /PRINT)
<Expression> STRING = ' 97'

1次元のBYTE型の配列は文字列に、2次元のBYTE型の配列は文字列の配列に変換される。

IDL> HELP, STRING([97B, 98B, 99B])
<Expression> STRING = 'abc'
IDL> HELP, STRING(BINDGEN(2, 2) + 65B)
<Expression> STRING = Array[2]
IDL> PRINT, STRING(BINDGEN(2, 2) + 65B)
AB CD

BYTE関数(またはFIX(TYPE=1)関数)で文字列をBYTE型に変換する場合も、ASCIIコードが返される。単純に文字列表記に対応する数値に変換する場合は、FIX関数にTYPE = 1 と /PRINT キーワードをつける。

IDL> HELP, BYTE('123')
<Expression> BYTE = Array[3]
IDL> PRINT, BYTE('123')
49 50 51
IDL> HELP, FIX('123', TYPE = 1, /PRINT)
<Expression> BYTE = 123

数値型の型変換関数は、変換先の型のサイズが変換元より小さいとき、デフォルトでは変換元の下位ビットを返すが、2番目の引数でオフセットを指定することで上位ビットを返すこともできる。剰余やビット演算をしなくても、上位ビットのデータを切り出すことができる。次の例では、24bitカラーをRGBに分解している。

IDL> color = 'FF8040'x
IDL> PRINT, FORMAT='(Z0)', BYTE(color, 2)
FF
IDL> PRINT, FORMAT='(Z0)', BYTE(color, 1)
80
IDL> PRINT, FORMAT='(Z0)', BYTE(color, 0)
40
IDL> PRINT, FORMAT='(Z0)', BYTE(color, 0, 3)
40
80
FF

数値型の型変換関数は、3番目以降の引数で、関数が返す結果の次元を指定できる。結果の次元を指定した場合、入力データの型と次元は無視され単なるバイト列として取り扱われる。つまり、バイト列の内容を変化させることなく、データ型を変換できる。

IDL> a = BINDGEN(16)
IDL> PRINT, FORMAT='(16(Z02," "))', a
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
IDL> PRINT, FORMAT='(8(Z04," "))', FIX(a, 0, 8)
0100 0302 0504 0706 0908 0B0A 0D0C 0F0E
IDL> PRINT, FORMAT='(4(Z08," "))', LONG(a, 0, 4)
03020100 07060504 0B0A0908 0F0E0D0C

西田圭佑 (NISHIDA Keisuke)
nishida at kwasan.kyoto-u.ac.jp