oracle binary float,oracle binary_float

/ 我有一个表如下:

createtableA_TEST

(

id_nNUMBER,

val_f BINARY_FLOAT,

val_d BINARY_DOUBLE

);

//插入一条数据

INSERTINTOA_TEST(ID_N, VAL_F,VAL_D)VALUES(0.1,0.1,0.1);

//如出刚才的数据发现binary_float显示不对

SELECT*FROMA_TEST;

0818b9ca8b590ca3270a3433284dd417.png

// 用程序查询的结果是对的

ResultSetset=oracle_stmt

.executeQuery("select id_n, val_f, val_d from A_TEST");

while(set.next()) {

System.out.println(set.getString(1) +",   "

+set.getFloat(2)+", "

+set.getDouble(3));

}

//程序查询的返回值是这样的

// .1,   0.1, 0.1

先了解下binary_float与binary_double 的内存存储方式:

http://blog.csdn.net/yidian815/article/details/12912661

binary_float 4字节 32位:

符号位S(1位)指数位E(8位)尾数位M(23位)

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

binary_double 8 字节 64位

符号位S(1位)指数位E(11位)尾数位M(52位)

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

与浮点数对应数学值计算方法为:v=(-1)^s*M*2^E.

为了便于比较两个浮点数的大小,指数部分采用无符号整数来存储,但是为了解决指数为负数的情况,IEEE 754规定,指数域的存储值为实际值和指数偏移量之和,指数偏移量的计算方法为2^(e-1) - 1

指数E(存储值) = V(实际值) + 2^(e-1) – 1(e为指数位数)

如E(存储值) 129,那么V(实际值) = 129 – 2 ^ (8-1) -1 = 2

例子:

123.625(10进制)à1111011.101(2进制)à1.111011101*2^6。

将1.111011101去除首部的1(任何二进制转换为科学计数法后,其整数部分必为1(尾数域范围为【1-2)),因此可以在尾数域中忽略该位,以便存储更多的数据

M = 1.111011101à111011101à11101110100000000000000(填充0)

S = 0

E = 10000101

按照相反的过程,我们可以推倒出0 10000101 11101110100000000000000à

0   134   11101110100000000000000à

0   6   1.111011101à1.111011101*2^6à123.625

根据上面的理论0.1(十进制)à0.0001 1001 1001 1001 10011001  ……

十进制小数转二进制小数使用乘2取整数法:

0.1*2=0.2整数为:0

0.2*2=0.4整数为:0

0.4*2=0.8整数为:0

0.8*2=1.6整数为:1

0.6*2=1.2整数为:1

0.2*2=0.4  …

二进制小数转十进制小数:

0.abcd = a *2^-1 + b * 2^-2 + c * 2^-3 …..

java代码实现二进制与十进制相互转换:

publicclassTodeimal {

publicstaticvoidmain(String[]args)throwsException {

Todeimalt=newTodeimal();

Listbinary=t.toBinary(0.1D, 23);

System.out.println();

t.toDecimal(binary);

t.toDecimal("00011001100110011001101",23);

}

publicvoidtoDecimal (Stringbinary,intmax){

doubleres= 0;

intj= 0;

for(inti=0;i

intbit= Integer.valueOf(String.valueOf(binary.charAt(i)));

res+=bit* Math.pow(2, --j);

}

System.out.println("四舍五入: "+res);

}

publicvoidtoDecimal (Listbinary) {

doubleres= 0;

intj= 0;

for(Integerb:binary) {

res+=b* Math.pow(2, --j);

}

System.out.println("不舍入: "+res);

}

publicList toBinary(Doublef,intmax){

if(f>= 1 ||f<= 0)

returnnull;

Listlist=newArrayList();

intbits= 0;

while(true) {

f= calc(f,list);

bits++;

if(bits== 50) {

System.out.println();

}

if(bits==max)

break;

}

System.out.println("len: "+list.size());

for(Integeri:list) {

System.out.print(i);

}

returnlist;

}

privateDouble calc(Doublef,Listlist){

if(f== 0 )

return-1D;

Doublet=f* 2;

if(t>= 1) {

list.add(1);

returnt- 1;

}else{

list.add(0);

returnt;

}

}

}

通过上面的计算方法把0.1存储数据库再取出来结果应该是:

selectto_char(id_n),to_char(val_f), val_f, to_char(val_d), val_d

fromA_TEST;

binary_float: 1.00000001E-001

binary_double: 1.0000000000000001E-001

由于plsql在显示两种类型时取值精度不一样就成了不同的显示效果

为了证明是显示精度的问题:

INSERTINTOA_TEST(ID_N, VAL_F,VAL_D)

VALUES(0.1,0.5, to_number(1.0000000000000101E-001))

同样在程序中查询的效果也是因为精度问题所以显示没有问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值