FLOAT DOUBLE 精度 以及和0的比较

1. 范围
  float和double的范围是由指数的位数来决定的。
  float的指数位有8位,而double的指数位有11位,分布如下:
  float:
  1bit(符号位) 8bits(指数位) 23bits(尾数位)
  double:
  1bit(符号位) 11bits(指数位) 52bits(尾数位)
  于是,float的指数范围为-127~+128,而double的指数范围为-1023~+1024,并且指数位是按补码的形式来划分的。
  其中负指数决定了浮点数所能表达的绝对值最小的非零数;而正指数决定了浮点数所能表达的绝对值最大的数,也即决定了浮点数的取值范围。
  float的范围为-2^128 ~ +2^128,也即-3.40E+38 ~ +3.40E+38;double的范围为-2^1024 ~ +2^1024,也即-1.79E+308 ~ +1.79E+308。

2.  精度
  float和double的精度是由尾数的位数来决定的。浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个隐含着的“1”,由于它是不变的,故不能对精度造成影响。
  float:2^23 = 8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字;
  double:2^52 = 4503599627370496,一共16位,同理,double的精度为15~16位。

3.Oracle中Number类型

在Oracle中Number类型可以用来存储0,正负定点或者浮点数,可表示的数据范围在
1.0 * 10(-130) —— 9.9...9 * 10(125) {38个9后边带88个0}
的数字,当Oracle中的数学表达式的值>=1.0*10(126)时,Oracle就会报错。
Number的数据声明如下:
表示        作用        说明
Number(p, s)        声明一个定点数        p(precision)为精度,s(scale)表示小数点右边的数字个数,精度最大值为38,
Number(p)        声明一个整数        相当于Number(p, 0)
Number        声明一个浮点数        其精度为38,要注意的是scale的值没有应用,也就是说scale的指不能简单的理解为0,或者其他的数。

定点数的精度(p)和刻度(s)遵循以下规则:
?        当一个数的整数部分的长度 > p-s 时,Oracle就会报错
?        当一个数的小数部分的长度 > s 时,Oracle就会舍入。
?        当s(scale)为负数时,Oracle就对小数点左边的s个数字进行舍入。
?        当s > p 时, p表示小数点后第s位向左最多可以有多少位数字,如果大于p则Oracle报错,小数点后s位向右的数字被舍入

4.验证
create or replace function  func_test(p_type number) return number
is
/*
 功能:基于警度图数据同步
*/
 l_cnt number;
begin
 select p_type into l_cnt from dual;
 return l_cnt;
end func_test;
/
show err;

5.结论

number 的总长度是40位,其中可能包括:小数点,负号位。

select to_char(func_test(-987.1234567891234567891234567891234567891234)) from dual;
-987.12345678912345678912345678912345679   //包括小数点及负号位共40位
select to_char(func_test(9876.1234567891234567891234567891234567891234)) from dual;
9876.12345678912345678912345678912345679   //4位整数+小数点+35位小数=40位
select to_char(func_test(987.1234567891234567891234567891234567891234)) from dual;
987.123456789123456789123456789123456789   //3位整数+小数点+36位小数=40位
select to_char(func_test(1234567891234567891234567891234567891234)) from dual;
1234567891234567891234567891234567891234   //40位整数
select to_char(func_test(12345678912345678912345678912345678912345)) from dual;
1.2345678912345678912345678912345679E+40   //41位时精度发生丢失
1.2345678912345678912345678912345679×10^40 即 12345678912345678912345678912345678900000

浮点变量与零值比较 
 【规则4-3-3】不可将浮点变量用“==”或“!=”与任何数字比较。
 
千万要留意,无论是float还是double类型的变量,都有精度限制。所以一定要避免将浮点变量用“==”或“!=”与数字比较,应该设法转化成“> =”或“ <=”形式。
 
假设浮点变量的名字为x,应当将
 
if   (x   ==   0.0)   //   隐含错误的比较
 
转化为
   
if   ((x> =-EPSINON)   &&   (x <=EPSINON)) 
其中EPSINON是允许的误差(即精度)。
 

EPSINON的值应大于你所用编译器的float(double)的精度12个数量级。千万不能等于甚至小于浮点精度,否则就跟直接比较一样了。 这个问题有必要搞懂。许多论坛上经常有人问,为什么floatdouble型不能用来控制switch流程?弄懂本帖问题后,就不会再提那样的傻问题了。

floatdouble的精度是由尾数的位数来决定的。浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个隐含着的“1”,由于它是不变的,故不能对精度造成影响。
  float
2^23 = 8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字;  double2^52 = 4503599627370496,一共16位,同理,double的精度为15~16位。

 

以下摘自《林锐-高质量c++c编程指南》 
/*   ----------------------------------------------------------------------------   */ 

if语句是C++/C语言中最简单、最常用的语句,然而很多程序员用隐含错误的方式写if语句。本节以“与零值比较”为例,展开讨论。
 

4.3.1   布尔变量与零值比较
 
&#61548; 【规则4-3-1】不可将布尔变量直接与TRUE、FALSE或者1、0进行比较。
 
根据布尔类型的语义,零值为“假”(记为FALSE),任何非零值都是“真”(记为TRUE)。TRUE的值究竟是什么并没有统一的标准。例如Visual   C++   将TRUE定义为1,而Visual   Basic则将TRUE定义为-1。
 
假设布尔变量名字为flag,它与零值比较的标准if语句如下:

if   (flag) //   表示flag为真 
if   (!flag) //   表示flag为假 
其它的用法都属于不良风格,例如: 
if   (flag   ==   TRUE) 
if   (flag   ==   1   ) 
if   (flag   ==   FALSE)     
if   (flag   ==   0) 

4.3.2   整型变量与零值比较
 
&#61548; 【规则4-3-2】应当将整型变量用“==”或“!=”直接与0比较。
 
假设整型变量的名字为value,它与零值比较的标准if语句如下:
 
if   (value   ==   0)     
if   (value   !=   0) 
不可模仿布尔变量的风格而写成 
if   (value) //   会让人误解   value是布尔变量
 
if   (!value)   

4.3.3   浮点变量与零值比较
 
&#61548; 【规则4-3-3】不可将浮点变量用“==”或“!=”与任何数字比较。
 
千万要留意,无论是float还是double类型的变量,都有精度限制。所以一定要避免将浮点变量用“==”或“!=”与数字比较,应该设法转化成“> =”或“ <=”形式。
 
假设浮点变量的名字为x,应当将
 
if   (x   ==   0.0)   //   隐含错误的比较
 
转化为
   
if   ((x> =-EPSINON)   &&   (x <=EPSINON)) 
其中EPSINON是允许的误差(即精度)。
 

4.3.4   指针变量与零值比较
 
&#61548; 【规则4-3-4】应当将指针变量用“==”或“!=”与NULL比较。
 
指针变量的零值是“空”(记为NULL)。尽管NULL的值与0相同,但是两者意义不同。假设指针变量的名字为p,它与零值比较的标准if语句如下:
 
if   (p   ==   NULL) //   p与NULL显式比较,强调p是指针变量
 
if   (p   !=   NULL) 
不要写成
 
if   (p   ==   0)   //   容易让人误解p是整型变量
 
if   (p   !=   0)         
或者
 
if   (p) //   容易让人误解p是布尔变量
 
if   (!p) 

4.3.5   对if语句的补充说明
 
有时候我们可能会看到   if   (NULL   ==   p)   这样古怪的格式。不是程序写错了,是程序员为了防止将   if   (p   ==   NULL)   误写成   if   (p   =   NULL),而有意把p和NULL颠倒。编译器认为   if   (p   =   NULL)   是合法的,但是会指出   if   (NULL   =   p)是错误的,因为NULL不能被赋值。
 
程序中有时会遇到if/else/return的组合,应该将如下不良风格的程序
 
if   (condition) 
return   x; 
return   y; 
改写为
 
if   (condition) 

return   x; 

else 

return   y; 

或者改写成更加简练的
   
return   (condition   ?   x   :   y);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值