最近有客户问关于NUMBER(p,s) 其中 精度P如何理解。
下面是官方在线文档的解释:
p is the precision, or the maximum number of significant decimal digits, where the most significant digit is the left-most nonzero digit, and the least significant digit is the right-most known digit. Oracle guarantees the portability of numbers with precision of up to 20 base-100 digits, which is equivalent to 39 or 40 decimal digits depending on the position of the decimal point.
1.怎么理解 20 base-100 digits ?
oracle 内部使用21个字节来存储number类型的数据,其中第一个字节存放 sign/offset/exponent.
符号/偏移量/指数的组合:具体介绍如下
-sign bit (0=negative 128 positive)
-offset always 65
-exponent (range from -65 to 62) in base 100
关于base 100的概念,这只是一种技术方式而已,我们都知道计算机世界使用0,1 二进制来操作,这个就是base 2,而我们经常使用的阿拉伯数字就是10进制的,那么就是base 10 。例如 10进制下345的表示方式为: 345=3*10^2+4*10^1+5*10^0,同样道理,用100进制来表示计数方式就是 base 100 ,
for example 12,34,56=12*100^2+34*100^1+56*100^0。
就像10进制下任何一位只能存放0~9以内数字一样,100进制下的任何“1”位数能存放0~99,oracle使用1个字节来存放100进制的每“1”位,共计有20个,所以oracle能存放的最大数字是(这里暂不考虑指数部分)99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,为了内部实现,oracle实际上在存储每“1”位的时候都+1,也就是存在磁盘上就是 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100.
2、如何理解精度的概念
如上所述,不考虑指数位的情况最大数字是20个99,也就是40位。那么超过这个数字,oracle就会丢失精度,如
若是存储41位的两个数字99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,1
99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,2,因为有效精度是40位,最后新增1位会被忽略掉,作为指数增加1。所以oracle是无法区分这两个数字的,会
认为这两个数字相等,相减也不会等于1,而是0, 下面分别是41位数和40位数相减情况
SQL> select 9999999999999999999999999999999999999999-9999999999999999999999999999999999999998 delta_40bit from dual;
delta_40bit
——————————————————————————–
1
SQL> select 99999999999999999999999999999999999999993-99999999999999999999999999999999999999992 delta_41bit from dual;
delta_41bit
——————————————————————————–
0
虽然精度存在40位的问题,但是并不代表oracle只能保存小于41位的数字,因为还存在指数位,所以只要超过40位,
那么指数位就加1,(因为100进制的四舍五入的原因,0-49指数不变,50-99才加1), 所以指数位最大是62,那么表示62个100进制位,即10进制的124位,加上第一个2位,oracle最大能存放1.0 x 10126(注意,因为100进制最大是99,所以是不包含1.0 x 10126 )
所以:NUMBER(p,s) 精度P是用来指定到底能存放多大精度的数字,若是p=5,那么最大数字就是99999,
这个参数可以指定0-38,若是想存储39,甚至最大40位精度,那么就不指定,默认最高就是40位精度了。