`

mysql中float、double数据类型的问题

阅读更多

       总结:对于单精度浮点数Float:  当数据范围在+-13107265536×2以内的时候,float数据精度是正确的,但是超出这个范围的数据就不稳定,没有发现有相关的参数设置建议:将float改成double或者decimal,两者的差别是double是浮点计算,decimal是定点计算,会得到更精确的数据。

 

分析如下:

    一、浮点数的概念及误差问题:   

浮点数是用来表示实数的一种方法,它用 M(尾数) * B( 基数)E(指数)次方来表示实数,相对于定点数来说,在长度一定的情况下,具有表示数据范围大的特点。但同时也存在误差问题,这就是著名的浮点数精度问题!   

 浮点数有多种实现方法,计算机中浮点数的实现大都遵从 IEEE754 标准,IEEE754 规定了单精度浮点数和双精度浮点数两种规格,单精度浮点数用4字节(32bit)表示浮点数,格式是:1位符号位 8位表示指数 23位表示尾数;双精度浮点数8字节(64bit)表示实数,格式是:1位符号位 11位表示指数 52位表示尾数。同时,IEEE754标准还对尾数的格式做了规范:d.dddddd...,小数点左面只有1位且不能为零,计算机内部是二进制,因此,尾数小数点左面部分总是1。显然,这个1可以省去,以提高尾数的精度。由上可知,单精度浮点数的尾数是用24bit表示的双精度浮点数的尾数是用53bit表示的,转换成十进制:

2^24 - 1 = 16777215           

2^53 - 1 = 9007199254740991     

由上可见,IEEE754单精度浮点数的有效数字二进制是24位,按十进制来说,是8位;双精度浮点数的有效数字二进制是53位,按十进制来说,是16 位。

显然,如果一个实数的有效数字超过8位,用单精度浮点数来表示的话,就会产生误差!同样,如果一个实数的有效数字超过16位,用双精度浮点数来表示,也会产生误差!

例如对于 1310720000000000000000.66 这个数,有效数字是24位,用单精度或双精度浮点数表示都会产生误差,只是程度不同:   

单精度浮点数: 1310720040000000000000.00   

双精度浮点数: 1310720000000000000000.00   

双精度差了 0.66 ,单精度差了近4万亿!以上说明了因长度限制而造成的误差,但这还不是全部!采用IEEE754标准的计算机浮点数,在内部是用二进制表示的,但在将一个十进制数转换为二进制浮点数时,也会造成误差,原因是不是所有的数都能转换成有限长度的二进制数。对于131072.32 这个数,其有效数字是8位,按理应该能用单精度浮点数准确表示,为什么会出现偏差呢?看一下这个数据二进制尾数就明白了 10000000000000000001010001......显然,其尾数超过了24bit,根据舍入规则,尾数只取 100000000000000000010100,结果就造成测试中遇到的奇怪现象!131072.68 用单精度浮点数表示变成 131072.69 ,原因与此类似。实际上有效数字小于8位的数,浮点数也不一定能精确表示,7.22这个数的尾数就无法用24bit二进制表示,当然在数据库中测试不会有问题(舍入以后还是7.22),但如果参与一些计算,误差积累后,就可能产生较大的偏差。

    二、mysql  oracle中的数值类型:   

问题是不是只有 mysql 存在呢?

显然不是,只要是符合IEEE754标准的浮点数实现,都存在相同的问题。     

mysql中的数值类型(不包括整型):   

 

IEEE754 浮点数: float(单精度),double或 real(双精度)

定点数: decimal 或 numeric    

oracle中的数值类型oracle  浮点数 :number (注意不指定精度)   

IEEE754浮点数 BINARY_FLOAT(单精度BINARY_DOUBLE (双精度)

FLOATFLOAT(n) ansi要求的数据类型)  定点数number(p,s)    

如果在oracle中,用BINARY_FLOAT等来做测试,结果是一样的。     

因此,在数据库中,对于涉及货币或其他精度敏感的数据,应使用定点数来存储,对mysql来说是 decimal,对oracle来说就是number(p,s)。双精度浮点数,对于比较大的数据同样存在问题!

    三、编程中也存在浮点数问题:   

不光数据库中存在浮点数问题,编程中也同样存在,甚至可以说更值得引起注意!   

通过上面的介绍,浮点数的误差问题应该比较清楚了。如果在程序中做复杂的浮点数运算,误差还会进一步放大。因此,在程序设计中,如果用到浮点数,一定要意识到可能产生的误差问题。不仅如此,浮点数如果处理不好,还会导致程序BUG

看下面的语句:

if (x != y)

{

z = 1 / (x -y);

}

这个语句看起来没有问题,但如果是浮点数,就可能存在问题!

再看下面的语句会输出什么结果:

public class Test

public static void main(String[]args)

throws Exception

{

     System.out.print("7.22-7.0=" + (7.22f-7.0f)); 

}     

我们可能会想当然地认为输出结果应该是 0.22 ,实际结果却是 0.21999979 !      

因此,在编程中应尽量避免做浮点数的比较,否则可能会导致一些潜在的问题!     

除了这些,还应注意浮点数中的一些特殊值,如 NaN+0-0+无穷、-无穷等,IEEE754虽然对此做了一些约定,但各具体实现、不同的硬件结构,也会有一些差异,如果不注意也会造成错误!

 

 

四、总结:   

从上面的分析,我们可以得出以下结论: 

1、浮点数存在误差问题;   

2、对货币等对精度敏感的数据,应该用定点数表示或存储;   

3编程中,如果用到浮点数,要特别注意误差问题,并尽量避免做浮点数比较   

4要注意浮点数中一些特殊值的处理   

  

 

本文来源于:http://blog.163.com/bbluesnow@126/blog/static/27784545201241610615201/

分享到:
评论

相关推荐

    MySQL中Decimal类型和Float Double的区别(详解)

    MySQL中存在float,double等非标准数据类型,也有decimal这种标准数据类型。 其区别在于,float,double等非标准类型,在DB中保存的是近似值,而Decimal则以字符串的形式保存数值。 float,double类型是可以存浮点数...

    Mysql支持的数据类型(总结)

     Mysql支持所有标准SQL中的数值类型,其中包括严格数据类型(INTEGER,SMALLINT,DECIMAL,NUMBERIC),以及近似数值数据类型(FLOAT,REAL,DOUBLE PRESISION),并在此基础上进行扩展。  扩展后增加了TINYINT,...

    mysql下float类型使用一些误差详解

    mysql中float数据类型的问题总结 对于单精度浮点数Float: 当数据范围在±131072(65536×2)以内的时候,float数据精度是正确的,但是超出这个范围的数据就不稳定,没有发现有相关的参数设置建议:将float改成...

    MySQL数据库:表的字段类型.pptx

    这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似数值数据类型(FLOAT、REAL和DOUBLE PRECISION)。 关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。 BIT数据类型保存位字段...

    Java与MySQL中小数保存问题解析.pptx.pptx

    小数精度问题 在Java和MySQL中,小数的精度可能会受到限制,如float类型的小数只能...在设计数据库表结构时,需要对涉及小数的字段选择合适的数据类型,如DECIMAL、FLOAT或DOUBLE等,以保证数据的准确存储和正确计算。

    mysql创建表方法.zip

    MySQL 创建表是一个基础的数据库操作,它涉及到定义表的结构,包括列名、数据类型、约束等。下面我将详细解释如何在 MySQL 中创建表,并给出一个完整的例子。 • 表名:你想要创建的表的名称。 • 列名:表中的列...

    Mysql支持的数据类型(列类型总结)

    Mysql支持所有标准SQL中的数值类型,其中包括严格数据类型(INTEGER,SMALLINT,DECIMAL,NUMBERIC),以及近似数值数据类型(FLOAT,REAL,DOUBLE PRESISION),并在此基础上进行扩展。 扩展后增加了TINYINT,MEDIUMINT,BIGINT...

    三种常用的MySQL 数据类型

    这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似数值数据类型(FLOAT、REAL和DOUBLE PRECISION)。 关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。 BIT数据类型保存位字段...

    MySQL所支持的数据类型与表字段约束类型的学习教程

    MySQL 主要的数据类型分为数值类型、字符串(文本)类型、时间日期类型和其他类型几类。 数值类型 数值类型说明: 补充说明 在 int(integer) 系列中,只能存储整型值,且可以在后面用括号指定显示的尺寸(M),...

    MySQL数据类型中DECIMAL的用法实例详解

    在MySQL数据类型中,例如INT,FLOAT,DOUBLE,CHAR,DECIMAL等,它们都有各自的作用,下面我们就主要来介绍一下MySQL数据类型中的DECIMAL类型的作用和用法。 一般赋予浮点列的值被四舍五入到这个列所指定的十进制数。...

    深入了解mysql的4种常用、重要的数据类型

    下面我们来看一下mysql的重要数据类型 1、数值类型可以划分为数值类型:整型,浮点十进制类型。 所谓的“十进制”是指decimal和numeric,他们是同一类型的。严格地说,它不是一个数字类型,因为他们实际上是作为字符...

    MySQL学习第六天 学习MySQL基本数据类型

     MySQL支持所有标准SQL中的数值类型,其中包括严格数据类型(INTEGER、SMALLINT、DECIMAL、NUMBERIC),以及近似数值数据类型(FLOAT、REAL、DOUBLE、PRESISION),并在此基础上进行扩展。扩展后增加了TINYINT、MED

    mysql面试题目大全

    FLOAT类型数据可以存储⾄多8位⼗进制数,并在内存中占4字节。 DOUBLE类型数据可以存储⾄多18位⼗进制数,并在内存中占8字节。 2. 字段为什么要求定义为not null? MySQL官⽹这样介绍: NULL columns require ...

    MySQL 数据类型

    这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似数值数据类型(FLOAT、REAL和DOUBLE PRECISION)。 关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。 BIT数据类型保存位字段...

    常问的MySQL面试题集合

    FLOAT类型数据可以存储至多8位十进制数,并在内存中占4字节。   DOUBLE类型数据可以存储至多18位十进制数,并在内存中占8字节。   问题5:如何在MySQL种获取当前日期? SELECT CURRENT_DATE(); 问题6:...

    MySQL面试题,经典

    1、一张表,里面有 ID 自增主键,当 insert 了 17 条记录之后,删除了第 15,16,17...16、TIMESTAMP 在 UPDATE CURRENT_TIMESTAMP 数据类型上做什么 17、主键和候选键有什么区别 18、如何使用 Unix shell 登录 Mysql ...

    分析MySQL的数据类型以及建库策略

    小数类,即浮点数类型,根据精度的不同,有FLOAT和DOUBLE两种。日期和时间类型比较简单,无非是DATE、TIME、DATETIME、TIMESTAMP和YEAR等几个类型。枚举类型,最多可以定义65535种不同的字符串从中做出选择,只能...

    mysql8.0.19基础数据类型详解

    mysql基础数据类型 mysql常用数据类型概览 ![1036857-20170801181433755-146301178](D:\笔记\mysql\复习\1036857-20170801181433755-146301178.png)1. 数字: 整型:tinyinit int bigint 小数: float :在位数...

    mysql5.5.28.zip

    多样的数据类型,包括有/无符号1,2,3,4,8字节integers,FLOAT,DOUBLE,CHAR,VARCHAR,TEXT,BLOB,DATE,DATETIME,YEAR,SET,ENUM;非常灵活和安全的权限系统,密码加密;为Windows提供ODBC接口,可通过...

    深入浅出Mysql – 基础篇(列类型/运算符/函数)

    MySQL支持所有标准SQL中的数值类型,其中包括严格数值类型(INTEGER、SMALLINT、DECIMAL 和 NUMERIC ),以及近似数值数据类型(FLOAT、REAL 和 DOUBLE,PRECISION),并在此基础上做了扩展。扩展后増加了 TINYINT、MED

Global site tag (gtag.js) - Google Analytics