oracle比较浮点与整数,float与double的范围和精度 不同类型和0比较

论坛 期权论坛 脚本     
已经匿名di用户   2022-4-20 22:34   2971   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)的精度1到2个数量级。千万不能等于甚至小于浮点精度,否则就跟直接比较一样了。这个问题有必要搞懂。许多论坛上经常有人问,为什么float或double型不能用来控制switch流程?弄懂本帖问题后,就不会再提那样的傻问题了。

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

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

if语句是C++/C语言中最简单、最常用的语句,然而很多程序员用隐含错误的方式写if语句。本节以“与零值比较”为例,展开讨论。4.3.1布尔变量与零值比较【规则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整型变量与零值比较【规则4-3-2】应当将整型变量用“==”或“!=”直接与0比较。假设整型变量的名字为value,它与零值比较的标准if语句如下:if (value == 0)

if (value != 0)不可模仿布尔变量的风格而写成if (value) //会让人误解value是布尔变量if (!value)

4.3.3浮点变量与零值比较【规则4-3-3】不可将浮点变量用“==”或“!=”与任何数字比较。千万要留意,无论是float还是double类型的变量,都有精度限制。所以一定要避免将浮点变量用“==”或“!=”与数字比较,应该设法转化成“> =”或“ <=”形式。假设浮点变量的名字为x,应当将if (x == 0.0) //隐含错误的比较转化为if ((x> =-EPSINON) && (x <=EPSINON))其中EPSINON是允许的误差(即精度)。4.3.4指针变量与零值比较【规则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 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP