0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Db2目線で見た Oracle NUMBERの謎の解明

Last updated at Posted at 2020-04-16

#NUMBERって何?

##Db2のDECIMALとOracleのNUMBERは、似て非なるもの?
OracleのNUMBERでは「マイナスの位取り」や、「精度以上の位取り」が指定できる。
Db2畑で育った私にとって、これは非常な驚きでした。
しかし、規則立てて考察すると「なるほど」と理解ができたので、それをまとめておこうと思います。

###NUMBERの指定方法###
NUMBER(p,s)
  精度p(1〜38桁)、位取りs(-84〜127桁:省略時 0)

これを見た私の衝撃。
「位取りがマイナスって何!」
「精度が38までなのに、127桁まで位取りが指定できるって、どういうこと?」

Db2のDECIMALの位取りは0か正数であり、指定できるのは最大でも精度と同じ値までなので理解しやすいけど、いったいこれらはどういう範囲の数字を意味するのか?

##■マイナスの位取り

Oracleのマニュアルには、マイナスの位取りに関して以下の説明があります。
「位取りが負の場合、小数点の左側にある桁数です。この場合は最下位有効桁を含みません。位取りが負の場合、実際のデータは整数部分の右から指定された桁数のみ丸められるため、最下位有効桁は小数点の左側になります。たとえば、(10,-2)と指定すると100の位まで丸められます。」

説明だけ読んでも全くピンとこないので、NUMBER(6,-3)を例に実際にOracleで値を入れて試してみました。

[1] マイナスの位取りのOracleでのテスト結果
[1] マイナスの位取りのOracleでのテスト結果.png

説明にはマイナスの数字は「小数点の左側にある桁数」とありましたが、[1]の結果を見ると、なるほど、整数部分の0の数ということですね!
つまり、マイナス3の位取り指定の場合は“下3桁を000にする整数、即ち1000の単位になるように四捨五入する”という意味で、1000未満の数は四捨五入され、0か1000になる事が分かりました。

では、なぜマイナスの位取りだとそうなるのか?

最初はNUMBERの独自の決め事かと思っていたのですが、ある法則を作成して当てはめてみた結果、「そうか、そうなるのか」と納得できました。

その法則とは、ちょっと数学的な話になってしまいますが、以下のようになります。

まず前提として、精度(p)と位取り(s)を指定するということは、
・精度は有効数字の桁数なので、使用できる数字は1~最大は9がp個分までという意味。
・位取りは小数点以下の位なので、10のs乗分の1の小数まで位取りがあるという意味。
であり、これはDb2のDECIMALでも同じです。

そして、(p,s)で表される数の0を除く正の最小値と最大値は、
最小値 1×((10のs乗)分の1) 
最大値 (9がp個)×((10のs乗)分の1)
 
という計算ルールで表現できます。

具体例でいうと、(4,1)の指定であればp=4、s=1なので、
最小値  1×((10の1乗)分の1) = 1 ×(1/10)= 0.1
最大値 (9999)×((10の1乗)分の1) = 9999 ×(1/10)= 999.9

となります。

このルールに則して、いくつかの例をEXCELで計算させてみました。

[2] 精度(p)と位取り(s)による、表現できる正の最小値と最大値の範囲
[2] 精度(p)と位取り(s)による、表現できる正の最小値と最大値の範囲.png

そこで、このEXCELに位取り(s)がマイナスの(6,-3)を指定してみると、その結果は。

[3] マイナスの位取りの結果
[3] マイナスの位取りの結果.png
あら、最小値が1000になった。

つまり(10^B7)の部分は10のマイナス3乗となるので(10の3乗)分の1=1000分の1、
とすると、1/(10^B7) は1÷(1000分の1) となり、答えは1000で単に10の3乗となる!

なるほど、位取りがマイナス値(ここでは-sとします)ということは、逆に10のs乗を有効数字に掛けるということだったのか、と納得。
(子どもの頃の数学の知識が、少し役立った気がします。)

では、精度(p)より大きい位取り(s)の場合を、このルールに当てはめてみたらどうなるでしょうか?

##■精度(p)より大きい位取り(s)
いくつかの例を当てはめてみました。

[4] 精度(p)と同じかそれより大きい位取り(s)を指定した結果(精度(p)≦位取り(s)の例)
[4] 精度(p)と同じかそれより大きい位取り(s)を指定した結果(精度(p)≦位取り(s)の例).png

この結果から、sがpと同じかそれ以上の場合、表現できる正の数は必ず1未満、即ち 0.xxx であること、また最大値は小数点以下の9の前にs - pの差分の数だけ先行0が増えるということが分ります。

例えば、NUMBER(4,6)の場合は小数点以下の桁数は6桁だが、有効数字は4桁までなので、小数点以下は右から4桁の9999までしか埋められず、残りの2桁は00となり、 0.009999が最大値となります。よって0.009999より1つ上の位になる0.01以上の数字は範囲外になるという制約が加わるということになります。

では実際はということで、OracleのNUMBER(4,6)に値を挿入してみました。

[5] Oracleでの確認
[5] Oracleでの確認.png
この結果から、精度(p)より大きい位取り(s)の場合も同じルールに則っていることが確認できました。

以上が、Db2のDECIMALにはないNUMBERの精度(p)と位取り(s)の指定について調べてみた結果です。

結局、これらはNUMBER独自のルールということではなく、DECIMALと同じ規則に則ったものだった!
という事で、私にとっては目からウロコの発見でしたので、ご紹介させていただきました。

以上

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?