数値の表現
InterSystems IRIS で数値を表現する方法には 2 種類あります。
10 進形式
InterSystems IRIS では、10 進数は内部的に 2 つの部分で表されます。最初の部分は仮数、2 番目の部分は指数と呼ばれます。
-
仮数は、対象となる値の有効桁数で構成されます。符号付 64 ビット整数として保存され、その値の右側には小数点があると見なされます。精度を失うことなく表現できる指数 0 の最大の正の整数は 9,223,372,036,854,775,807、最大の負の整数は -9,223,372,036,854,775,808 です。
-
指数は、符号付バイトとして内部的に保存されます。値の範囲は 127 ~ -128 です。
これは、値の 10 進数の指数です。つまり、その数の値は、仮数に 10 の指数のべき乗を乗算したものになります。
例えば、ObjectScript リテラル値 1.23 の場合、仮数は 123 であり、指数は -2 です。
したがって、InterSystems IRIS がネイティブ形式で表現できる数値の範囲は、約 1.0E-128 ~ 9.22E145 になります。(最初の値は最小の指数を持つ最小の整数になります。2 番目の値は最も大きい整数で、小数点が左に移動して、それに従って指数が増加する形式で表されます。)
小数桁数が 18 の数値はすべて正確に表現できます。また、仮数が表現範囲内にある数値は、19 桁の値として正確に表現できます。
Note:
InterSystems IRIS では、数値を 10 進形式にする必要がない限り、仮数を正規化することはしません。したがって、仮数が 123 で指数が 1 の数と、仮数が 1230 で指数が 0 の数は同じものを表します。
$DOUBLE 形式
インターシステムズの $DOUBLE 形式は、IEEE-754–1985Opens in a new tab、具体的には 64 ビットのバイナリ (倍精度) 表現に準拠します。つまり、以下の 3 つの部分で構成されます。
-
符号ビット
-
2 つの指数 の 11 ビット乗。指数値には 1023 のバイアス分が含まれるので、$DOUBLE(1.0) の指数の内部値は 0 ではなく 1023 になります。
-
正の 52 ビット小数の仮数部仮数部は常に正の数値として処理され正規化されるため、仮数部として表されていなくても、1 ビットは先頭のバイナリ桁であると見なされます。したがって、仮数部は数値としては 53 ビット長になり、値 1 の後に暗黙の 2 進小数点、その後に小数の仮数部が続きます。これは、暗黙的に 2**52 で除算された整数として考えることができます。
整数として、0 ~ 9,007,199,254,740,992 のすべての値は正しく表現できます。大きな整数を正しく表現できるかどうかは、そのビット・パターンによります。
このデータ表現には、InterSystems IRIS のネイティブ形式にはない以下の 3 つのオプション機能があります。
これらの機能は、個別プロセスの場合は %SYSTEM.ProcessOpens in a new tab クラスの IEEEError()Opens in a new tab メソッド、システム全般の場合は Config.MiscellaneousOpens in a new tab クラスの IEEEError()Opens in a new tab メソッドを介してプログラム制御されます。
Important:
IEEE バイナリ浮動小数点表現を使用して計算すると、同じ IEEE 演算でも異なる結果が得られる場合があります。インターシステムズでは、以下に対して独自の実装を記述しています。
-
$DOUBLE バイナリ浮動小数点と 10 進数との間の変換。
-
$DOUBLE と数値文字列との間の変換。
-
$DOUBLE とその他の数値型との間の比較。
これにより、$DOUBLE 値を InterSystems IRIS データベースに挿入したり、InterSystems IRIS データベースからフェッチしたりするときに、すべてのハードウェア・プラットフォームで結果が同じになることが保証されます。
ただし、$DOUBLE 型を含むその他すべての計算では、InterSystems IRIS はベンダが提供する浮動小数点ライブラリのサブルーチンを使用します。そのため、同じ演算のセットでも、プラットフォームによってわずかな差異が生じる可能性があります。ただし、すべてのケースにおいて、インターシステムズの $DOUBLE の計算は、C の double 型で実行するローカルの計算と等しくなります。つまり、インターシステムズの $DOUBLE の計算に対するプラットフォーム間の差異は、最大でも、それぞれ同じプラットフォーム上で実行される C プログラムの IEEE 値の計算結果の差異に留まります。
SQL 表現
InterSystems SQL データ型の DOUBLE と DOUBLE PRECISION は、IEEE 浮動小数点数 (つまり $DOUBLE) を表します。SQL FLOAT データ型は、標準の InterSystems IRIS の10 進数を表します。
数値形式の選択
使用する形式の選択は、計算の要件に大きく依存します。InterSystems IRIS の 10 進形式では 18 桁を超える精度が許可されますが、$DOUBLE では 15桁しか保証されません。
多くの場合、10 進形式は使用法がより簡単で、結果も正確です。予想どおりの結果が返されるため、通常、(通貨計算などの) 10 進値の計算に使用されます。ほとんどの 10 進数の小数は、バイナリの小数ほど正確には表現できません。
それに対して、$DOUBLE 形式の数値の範囲は、ネイティブ形式で許可される 1.0E145 よりもはるかに大きい 1.0E308 になります。数値の範囲が重要となるアプリケーションでは、$DOUBLE を使用する必要があります。
データを外部で共有するアプリケーションでは、暗黙の変換対象とならないよう、データを $DOUBLE 形式で維持することも検討できます。他のほとんどのシステムでは、基礎となるハードウェア・アーキテクチャによって直接サポートされることから、バイナリ浮動小数点の表現に IEEE 標準を使用しています。したがって 10 進形式の値は、(例えば ODBC/JDBC、SQL、または言語バインディング・インタフェースを使用して) 情報交換前に変換する必要があります。
InterSystems IRIS の 10 進数に定義された範囲内に $DOUBLE 値がある場合、10 進数に変換して再度 $DOUBLE 値に戻すと、常に同じ数値が生成されます。$DOUBLE 値の精度は 10 進値よりも低いため、逆の場合はこのようにはなりません。
その理由から、可能であれば、いずれか 1 つのデータ表現のみを使用して計算を実行することをお勧めします。データ表現間で変換を繰り返すと、精度が落ちる場合があります。多くのアプリケーションでは、すべての計算に InterSystems IRIS の 10 進形式を使用できます。$DOUBLE 形式は、IEEE 形式を使用するシステムとデータを交換するアプリケーションのサポートを目的としています。
$DOUBLE ではなく、InterSystems IRIS の 10 進形式をお勧めする理由は、以下のとおりです。
-
InterSystems IRIS の 10 進形式は精度が高く、$DOUBLE の桁数が 16 未満であるのに対し、ほぼ 19 桁の精度を持っています。
-
InterSystems IRIS の 10 進形式では、正確に 10 進数の小数を表現できます。例えば、0.1 という値は InterSystems IRIS の 10 進形式では正確に 0.1 になりますが、バイナリの浮動小数点では同値となる値がないので、$DOUBLE 形式では語義的な近似値で 0.1 を表現する必要があります。
科学的数値では、以下の点でインターシステムズの 10 進形式よりもインターシステムズの $DOUBLE の方が有利です。
値の正確な表現
各数値形式には、保持できる有効桁数の限度があります。普通は、この限度よりも桁数が多ければ、自動的に精度が落ちると考えがちです。しかし、一般的にはこれは正しくありません。
この影響は、InterSystems IRIS の 10 進数値に最もよく見られます。単純に、値 9,223,372,036,854,775,807 が正確に表現できる最大の数値であると考えがちですが、その考えでは指数が無視されています。9,223,372,036,854,775,807,000,000 は、百万倍大きいですがこれも正確に表現できることは明らかです。値が許可された範囲内にある、指数が 0 の他のすべての数値について、同じことが当てはまります。しかし、これは、10 進数の全範囲内で取り得るすべての数値ではありません。
この表現では、10 の累乗の代わりに 2 の累乗を数値に掛けること以外、状況は似ています。以下の特徴がある非常に単純なモデルを考えれば、この状況を図で示すことができます。
以下の表は、表現可能な値を示します。
指数 |
-4 |
-3 |
-2 |
-1 |
0 |
1 |
2 |
3 |
仮数 |
|
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0.0625 |
0.125 |
0.25 |
0.5 |
1 |
2 |
4 |
8 |
2 |
0.125 |
0.25 |
0.5 |
1 |
2 |
4 |
8 |
16 |
3 |
0.1875 |
0.375 |
0.75 |
1.5 |
3 |
6 |
12 |
24 |
4 |
0.25 |
0.5 |
1 |
2 |
4 |
8 |
16 |
32 |
5 |
0.3125 |
0.625 |
1.25 |
2.5 |
5 |
10 |
20 |
40 |
6 |
0.375 |
0.75 |
1.5 |
3 |
6 |
12 |
24 |
48 |
7 |
0.4375 |
0.875 |
1.75 |
3.5 |
7 |
14 |
28 |
56 |
以下の点に注意してください。
-
このモデルでは、仮数には 3 ビットしか使用しないので、1 桁の 10 進数には十分な精度がありません。9 という数値がありません。これを表現するには、仮数として 1001 が必要となり、これは明らかに長すぎるからです。
-
これらのバイナリ数値をすべて完全に正確な 10 進数文字列と正確に対照させるには、表現で有効な 4 桁の 10 進数を使用する必要があります。
-
0 ~ 56 の範囲の数値には表現できないものがあります。一例として 2.75 という値が挙げられます。 段階的に仮数を整数に変換すると、結果として 5.5、次に 11 という値が得られる一方で、これに対応して、指数が -1、次に -2 となります。しかし 11 は 3 ビットでは表現できない値なので、上記の表内にはありません。
以下の図では、この形式で表現できる値が、数直線上においてどのように分布しているかを示しています。図示するために、刻み幅を、最小の表現可能な値である 0.0625 (つまり 1/16) としています。数直線は、各直線が 4 単位分の長さ (つまり 64 刻み) となるように、折り返されています。X は、この形式で表現できる数値を示しています。配置可能な 56*16=896 個の位置のうち、正確に表現できるのは 64 個 (平均では 14 個中 1 個) のみです。
+0 +1 +2 +3
| | | |
0 XXXXXXXXX.X.X.X.X...X...X...X...X.......X.......X.......X.......
4 X...............X...............X...............X...............
8 X..............._...............X..............._...............
12 X..............._...............X..............._...............
16 X..............._..............._..............._...............
20 X..............._..............._..............._...............
24 X..............._..............._..............._...............
28 X..............._..............._..............._...............
32 X..............._..............._..............._...............
36 _..............._..............._..............._...............
40 X..............._..............._..............._...............
44 _..............._..............._..............._...............
48 X..............._..............._..............._...............
52 _..............._..............._..............._...............
56 X..............._..............._..............._...............
同様な状況が、InterSystems IRIS の 10 進数値にも当てはまります。正確に表現できる (指数が 0 の) 最大の整数は、9,223,372,036,854,775,807 です。説明の都合上、この値を MAX と呼びます。この結果、MAX*10 および (MAX-3)*100 も正確に表現できることになります。これらの指数は 0 ではありませんが、仮数は正確です。ただし、MAX+1 などのように正確に表現できない値もあります。
$DOUBLE 値でも、指数が InterSystems IRIS の場合のように 10 ではなく 2 の累乗である場合を除き、この現象が発生します。