Oracle 是大海,这里是它的一滴水!
http://songhefei.itpub.net
number 小议 (转)
上一篇 / 下一篇 2008-06-25 12:06:12 / 个人分类:Oracle internal
number数据内部存储时,以变长的数组来存放,数组里的每个元素占一个字节,最多20个元素。内部代码为2。number数据的存放格式为:<[length]>,sign bit/exponent,digit1,digit2,…,digit20
:e8_1Ad5OJ"lU/a0sign bit/exponent这部分叫做exponent byte。
P}4FbP-_0
V*iY/Zs$u@Q0exponent byte包括三部分:ITPUB个人空间6M6]^2t9h+T/E
v7xFk/bs/y0SQL> select dump(0) from dual;ITPUB个人空间Ai|j%M
(V^+Y N"]};t0DUMP(0)
4@ h(n-l&{6u$d v0----------------
ym6^.p#?S0Typ=2 Len=1: 128ITPUB个人空间v6A}-I&yCG
ITPUB个人空间(IM_&N&Sv B5C
来看一个非0的值:ITPUB个人空间&M*y E'E,]"E @Yn
SQL> select dump(25,16) from dual;ITPUB个人空间.ey!| `0|6_
_5`6[*PPu%?0DUMP(25,16)ITPUB个人空间4y uk7{yTk2@z
------------------
B3kV0Wv,m3a}0Typ=2 Len=2: c1,1a
M m"@9Ot-|:y0ITPUB个人空间 Hw9s+J+u"x?
则exponent byte为c1,也就是
j[2T4R6a%g!p0SQL> select to_number('c1','xx'),to_number('1a','xx') from dual;ITPUB个人空间*ES o0UN.d
9w&m(SV+h-x wZ0TO_NUMBER('C1','XX') TO_NUMBER('1A','XX')
:xg yB!P4e0-------------------- --------------------ITPUB个人空间Z(X$jkL9L6V]#?s;w
193 26ITPUB个人空间%u8W q5@ Bh4b|
qD@pJj*r/f0而193=128+65+0,也就是sign bit为128,offset为65,exponent为0。ITPUB个人空间w!jaP*TX%ex:yD
同时,oracle存储时,用1表示0,2表示1,依此类推。也就是说用显示的值减1就是实际的值。如下所示:ITPUB个人空间7Q/_8[#GkK
SQL> select dump(1,16) from dual;ITPUB个人空间.Q(wj!yd5E naW
ITPUB个人空间t4n$n&o1H^[
DUMP(1,16)ITPUB个人空间-Z'FZ&P8}C&MX
-----------------
[S|2Hx+}X8K@!d0Typ=2 Len=2: c1,2
oJJyLH`0
2`/}&g(u#r3\v2Co0因此,0xc11a就是:(26-1)*power(100,0)=25
R,F0t2}!mgx X0ITPUB个人空间{V M^g~8^p
再来看另一个例子:ITPUB个人空间,Cl4@MU b:hi
SQL> select dump(1234,16) from dual;ITPUB个人空间L/{a`y)zz
ITPUB个人空间UaL9L[ XM;W*E0W
DUMP(1234,16)
Dz&xm9OZV6I V0--------------------ITPUB个人空间f-y i.h&j2k0}
Typ=2 Len=3: c2,d,23ITPUB个人空间9LP'}Oe;] B'Q1t}
ITPUB个人空间3{e+[;^4f R
这里c2表示194,也就是194=128+65+1。
:mD,ykT-l)i0
c5F"kBWp0SQL> select to_number('c2','xx'),to_number('d','xx'),to_number('23','xx') from dual;ITPUB个人空间 V,r-m1Wg9L
ITPUB个人空间_ \+DcSb
TO_NUMBER('C2','XX') TO_NUMBER('D','XX') TO_NUMBER('23','XX')
`0{[,scmu*Z6~0-------------------- ------------------- --------------------
8~P d1P(|!o0 194 13 35
({T N|`8[/aG4U0
`$X0\4P F2D"r+Q0因此该数值为:(13-1)*power(100,1)+(35-1)*power(100,0)=1200+34=1234ITPUB个人空间|-H`)X(d:hF3Mi~ y
6M(JE/n\.}0如果数值为负数,则它的exponent byte的算法是一样的,只不过顺序是反过来的,从255开始计算。比如:
_ X g0jF ~'g0SQL> select dump(-25,16) from dual;
$c"U@0x.MyYG0ITPUB个人空间$y%{{8x:D ?%`{
DUMP(-25,16)ITPUB个人空间h4D v S{#XU#S
---------------------
8Nw3E_N*U'?j|0Typ=2 Len=3: 3e,4c,66ITPUB个人空间6xgyaqU
ITPUB个人空间l%R fv UI F _7Q*gN
SQL> select to_number('3e','xx'),to_number('4c','xx') from dual;ITPUB个人空间/OPV-hgoR
ITPUB个人空间*D|FSsa+s.A
TO_NUMBER('3E','XX') TO_NUMBER('4C','XX')
t`/a q[5W%_!~0C0-------------------- --------------------ITPUB个人空间?M;NuyQ7C#t_d
62 76ITPUB个人空间&r-m.^@L2H
负数的最后一位始终都是66,也就是说最后一位如果为66,则说明它是负数。
&VRm `y"q~gE0这时的exponent byte为:255-62=193=128+65+0
*a4yj\rX0同时,oracle在存放number型数据时,以100为基数,同时正数和负数互为相反数,也就是正数+负数=100。因此我们就有:(100-76-1)*power(100,0)=25ITPUB个人空间?Zck\}3Uz
加上符号位,则数值为-25
3J2iF4g&o*k0
XS;_I,o4^bk6t0我们在来看一个例子:
0[)WJu3uC'J e T0SQL> select dump(-1234,16) from dual;
o0ez/Smz%a0
pA%V;[|P/TR0DUMP(-1234,16)
A5@&{ ]%A)}0------------------------
8EP1R4Za bd!x0Typ=2 Len=4: 3d,59,43,66ITPUB个人空间qm }F%]-P
ITPUB个人空间[ r2y [4MdC
SQL> select to_number('3d','xx'),to_number('59','xx'),to_number('43','xx') from dual;ITPUB个人空间`kTrIZ\FU~b
` |9@,bi5o?0TO_NUMBER('3D','XX') TO_NUMBER('59','XX') TO_NUMBER('43','XX')ITPUB个人空间 yc [.HI"K&X?c jL
-------------------- -------------------- --------------------
p!yy efhl0 61 89 67
-lU#C(r3L uq O0ITPUB个人空间{ fR.Fq/}e;L(] Q/h,J
于是exponent byte为:255-61=194=128+65+1
y!X JE`+V0(100-89-1)*power(100,1)+(100-67-1)*power(100,0)=1200+24=1234ITPUB个人空间M+V XP1p
加上符号位,则数值为-1234ITPUB个人空间*p%C/U S0N[$X1o}
"pMfI2JE*f V5uLn2o0因此很明显,如果第一个字节大于等于128,则说明该数值为正数,并且exponent为:exponent = first byte - 128 - 65 = first byte - 193
:e8_1Ad5OJ"lU/a0sign bit/exponent这部分叫做exponent byte。
P}4FbP-_0
V*iY/Zs$u@Q0exponent byte包括三部分:ITPUB个人空间6M6]^2t9h+T/E
- sign bit:这表示高位bit,也就是128。并且我们有:
- 如果小于128,则数值为负数。
- 如果大于等于128,则数值为正数或0。
- offset,始终为65
- exponent:其范围从-65到62。该部分的值是基于100而进行的科学计数法。
v7xFk/bs/y0SQL> select dump(0) from dual;ITPUB个人空间Ai|j%M
(V^+Y N"]};t0DUMP(0)
4@ h(n-l&{6u$d v0----------------
ym6^.p#?S0Typ=2 Len=1: 128ITPUB个人空间v6A}-I&yCG
ITPUB个人空间(IM_&N&Sv B5C
来看一个非0的值:ITPUB个人空间&M*y E'E,]"E @Yn
SQL> select dump(25,16) from dual;ITPUB个人空间.ey!| `0|6_
_5`6[*PPu%?0DUMP(25,16)ITPUB个人空间4y uk7{yTk2@z
------------------
B3kV0Wv,m3a}0Typ=2 Len=2: c1,1a
M m"@9Ot-|:y0ITPUB个人空间 Hw9s+J+u"x?
则exponent byte为c1,也就是
j[2T4R6a%g!p0SQL> select to_number('c1','xx'),to_number('1a','xx') from dual;ITPUB个人空间*ES o0UN.d
9w&m(SV+h-x wZ0TO_NUMBER('C1','XX') TO_NUMBER('1A','XX')
:xg yB!P4e0-------------------- --------------------ITPUB个人空间Z(X$jkL9L6V]#?s;w
193 26ITPUB个人空间%u8W q5@ Bh4b|
qD@pJj*r/f0而193=128+65+0,也就是sign bit为128,offset为65,exponent为0。ITPUB个人空间w!jaP*TX%ex:yD
同时,oracle存储时,用1表示0,2表示1,依此类推。也就是说用显示的值减1就是实际的值。如下所示:ITPUB个人空间7Q/_8[#GkK
SQL> select dump(1,16) from dual;ITPUB个人空间.Q(wj!yd5E naW
ITPUB个人空间t4n$n&o1H^[
DUMP(1,16)ITPUB个人空间-Z'FZ&P8}C&MX
-----------------
[S|2Hx+}X8K@!d0Typ=2 Len=2: c1,2
oJJyLH`0
2`/}&g(u#r3\v2Co0因此,0xc11a就是:(26-1)*power(100,0)=25
R,F0t2}!mgx X0ITPUB个人空间{V M^g~8^p
再来看另一个例子:ITPUB个人空间,Cl4@MU b:hi
SQL> select dump(1234,16) from dual;ITPUB个人空间L/{a`y)zz
ITPUB个人空间UaL9L[ XM;W*E0W
DUMP(1234,16)
Dz&xm9OZV6I V0--------------------ITPUB个人空间f-y i.h&j2k0}
Typ=2 Len=3: c2,d,23ITPUB个人空间9LP'}Oe;] B'Q1t}
ITPUB个人空间3{e+[;^4f R
这里c2表示194,也就是194=128+65+1。
:mD,ykT-l)i0
c5F"kBWp0SQL> select to_number('c2','xx'),to_number('d','xx'),to_number('23','xx') from dual;ITPUB个人空间 V,r-m1Wg9L
ITPUB个人空间_ \+DcSb
TO_NUMBER('C2','XX') TO_NUMBER('D','XX') TO_NUMBER('23','XX')
`0{[,scmu*Z6~0-------------------- ------------------- --------------------
8~P d1P(|!o0 194 13 35
({T N|`8[/aG4U0
`$X0\4P F2D"r+Q0因此该数值为:(13-1)*power(100,1)+(35-1)*power(100,0)=1200+34=1234ITPUB个人空间|-H`)X(d:hF3Mi~ y
6M(JE/n\.}0如果数值为负数,则它的exponent byte的算法是一样的,只不过顺序是反过来的,从255开始计算。比如:
_ X g0jF ~'g0SQL> select dump(-25,16) from dual;
$c"U@0x.MyYG0ITPUB个人空间$y%{{8x:D ?%`{
DUMP(-25,16)ITPUB个人空间h4D v S{#XU#S
---------------------
8Nw3E_N*U'?j|0Typ=2 Len=3: 3e,4c,66ITPUB个人空间6xgyaqU
ITPUB个人空间l%R fv UI F _7Q*gN
SQL> select to_number('3e','xx'),to_number('4c','xx') from dual;ITPUB个人空间/OPV-hgoR
ITPUB个人空间*D|FSsa+s.A
TO_NUMBER('3E','XX') TO_NUMBER('4C','XX')
t`/a q[5W%_!~0C0-------------------- --------------------ITPUB个人空间?M;NuyQ7C#t_d
62 76ITPUB个人空间&r-m.^@L2H
负数的最后一位始终都是66,也就是说最后一位如果为66,则说明它是负数。
&VRm `y"q~gE0这时的exponent byte为:255-62=193=128+65+0
*a4yj\rX0同时,oracle在存放number型数据时,以100为基数,同时正数和负数互为相反数,也就是正数+负数=100。因此我们就有:(100-76-1)*power(100,0)=25ITPUB个人空间?Zck\}3Uz
加上符号位,则数值为-25
3J2iF4g&o*k0
XS;_I,o4^bk6t0我们在来看一个例子:
0[)WJu3uC'J e T0SQL> select dump(-1234,16) from dual;
o0ez/Smz%a0
pA%V;[|P/TR0DUMP(-1234,16)
A5@&{ ]%A)}0------------------------
8EP1R4Za bd!x0Typ=2 Len=4: 3d,59,43,66ITPUB个人空间qm }F%]-P
ITPUB个人空间[ r2y [4MdC
SQL> select to_number('3d','xx'),to_number('59','xx'),to_number('43','xx') from dual;ITPUB个人空间`kTrIZ\FU~b
` |9@,bi5o?0TO_NUMBER('3D','XX') TO_NUMBER('59','XX') TO_NUMBER('43','XX')ITPUB个人空间 yc [.HI"K&X?c jL
-------------------- -------------------- --------------------
p!yy efhl0 61 89 67
-lU#C(r3L uq O0ITPUB个人空间{ fR.Fq/}e;L(] Q/h,J
于是exponent byte为:255-61=194=128+65+1
y!X JE`+V0(100-89-1)*power(100,1)+(100-67-1)*power(100,0)=1200+24=1234ITPUB个人空间M+V XP1p
加上符号位,则数值为-1234ITPUB个人空间*p%C/U S0N[$X1o}
"pMfI2JE*f V5uLn2o0因此很明显,如果第一个字节大于等于128,则说明该数值为正数,并且exponent为:exponent = first byte - 128 - 65 = first byte - 193