单精度浮点数用4字节(32bit)表示浮点数

采用IEEE754标准的计算机浮点数,在内部是用二进制表示的

如:7.22用32位二进制是表示不下的。

所以就不精确了。

mysql中float数据类型的问题总结

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

1.float类型

float列类型默认长度查不到结果,必须指定精度,

比如 num  float,  insert into  table (num) values (0.12); select  * from table where num=0.12的话,empty set。

复制代码代码如下:

num float(9,7),  insert into  table (num) values (0.12); select  * from table where num=0.12的话会查到这条记录。

mysql> create table tt

-> (

-> num  float(9,3)

-> );

Query OK, 0 rows affected (0.03 sec)

mysql> insert into tt(num)values(1234567.8);

ERROR 1264 (22003): Out of range value for column 'num' at row 1

注:超出字段范围,无法插入

代码如下 复制代码

mysql> insert into tt(num)values(123456.8);

Query OK, 1 row affected (0.00 sec)

mysql> select  * from  tt;

+------------+

| num        |

+------------+

| 123456.797 |

+------------+

1 row in set (0.00 sec)

注:小数位数不够,自动补齐,但是存在一个问题就是如上的近似值。

复制代码代码如下:

mysql> insert into tt(num)values(123456.867);

Query OK, 1 row affected (0.04 sec)

mysql> select * from   tt;

+------------+

| num        |

+------------+

| 123456.797 |

| 123456.797 |

| 123456.867 |

+------------+

3 rows in set (0.00 sec)

mysql> select  * from tt where  num=123456.867;

+------------+

| num        |

+------------+

| 123456.867 |

+------------+

1 row in set (0.00 sec)

mysql> insert into tt(num)values(2.8);

Query OK, 1 row affected (0.04 sec)

mysql> select * from   tt;

+------------+

| num        |

+------------+

| 123456.797 |

| 123456.797 |

| 123456.867 |

|      2.800 |

+------------+

4 rows in set (0.00 sec)

mysql> select  * from tt where  num=2.8;

+-------+

| num   |

+-------+

| 2.800 |

+-------+

1 row in set (0.00 sec)

mysql> insert into tt(num)values(2.888888);

Query OK, 1 row affected (0.00 sec)

mysql> select  * from  tt;

+------------+

| num        |

+------------+

| 123456.797 |

| 123456.797 |

| 123456.867 |

|      2.800 |

|      2.889 |

+------------+

5 rows in set (0.00 sec)

注:小数位数超了,自动取近似值。

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

浮点数是用来表示实数的一种方法,它用 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(双精度)FLOAT,FLOAT(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、要注意浮点数中一些特殊值的处理

注意事项

MYSQL 5.022中,

如果某个字段 f是float类型,那么在查询的时候,sql语句为:

select * from T where f = 2.2;

那么即使表中有2.2的数据也不能被查询到.

此时解决方法有2种:

1.将float改为double类型,不会出现这种问题.但是如果数据库中数据量庞大,或者修改量太大,则不适合这个方法.这个方法只适合设计数据库的初期阶段.

2.设置float的精度然后进行查询就可以了.

如果要精确到3位,则:select * from T where format(f,3) = format(2.2,3);

但是,精度不能超过6.否则出错.因为float类型最多允许精确到小数点后6位.

mysql float 精度阶段_mysql下float类型使用一些误差详解相关推荐

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

    单精度浮点数用4字节(32bit)表示浮点数 采用IEEE754标准的计算机浮点数,在内部是用二进制表示的 如:7.22用32位二进制是表示不下的. 所以就不精确了. mysql中float数据类型的 ...

  2. mysql order by 语句_Mysql优化order by语句的方法详解

    本篇文章我们将了解ORDER BY语句的优化,在此之前,你需要对索引有基本的了解,不了解的老少爷们可以先看一下我之前写过的索引相关文章.现在让我们开始吧. MySQL中的两种排序方式 1.通过有序索引 ...

  3. mysql innodb事务中_MySQL InnoDB如何保证事务特性示例详解

    前言 如果有人问你"数据库事务有哪些特性"?你可能会很快回答出原子性.一致性.隔离性.持久性即ACID特性.那么你知道InnoDB如何保证这些事务特性的吗?如果知道的话这篇文章就可 ...

  4. mysql 存储引擎作用_MySQL常用存储引擎功能与用法详解

    MySQL存储引擎主要有两大类: 1. 事务安全表:InnoDB.BDB. 2. 非事务安全表:MyISAM.MEMORY.MERGE.EXAMPLE.NDB Cluster.ARCHIVE.CSV. ...

  5. mysql 半同步 原理_MySQL半同步复制原理与配置详解

    一 .异步.同步和半同步复制概念 异步复制(Asynchronous replication),MySQL默认的复制是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已 ...

  6. mysql ibd文件还原_MySQL单表ibd文件恢复方法详解

    前言: 随着innodb的普及,innobackup也成为了主流备份方式.物理备份对于新建slave,全库恢复的需求都能从容应对. 但当面临单表数据误删,或者单表误drop的情况,如果使用物理全备进行 ...

  7. 43. Systemd的Unit配置详解,unit文件位置,优先级,unit类型,unit文件字段详解,Unit/Service/Install字段,添加mysql服务等例子

    Systemd的Unit配置详解,unit文件位置和优先级,unit文件类型,unit文件字段详解,[Unit]字段,[Service]字段,[Install]字段,添加服务,创建.service 文 ...

  8. python布尔类型运算_Python对象类型及其运算方法(详解)

    基本要点: 程序中储存的所有数据都是对象(可变对象:值可以修改 不可变对象:值不可修改) 每个对象都有一个身份.一个类型.一个值 例: >>> a1 = 'abc' >> ...

  9. 【Android 应用开发】Ubuntu 下 Android Studio 开发工具使用详解 (旧版本 | 仅作参考)

    . 基本上可以导入项目开始使用了 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21035637 ...

最新文章

  1. 业界丨全球AI人才排行榜:美国第一,中国仅排名第7
  2. linux的套接口和管道
  3. bash给脚本加进度条_进度条——shell脚本实现
  4. Cisco pix515配置实例
  5. python2和python3如何共存_Windows下python2和python3的共存设置
  6. uva437巴比伦塔
  7. JVM内存溢出分析-实战JVM(二)
  8. mysql字段重命名_MySQL中使用SQL语句对字段进行重命名
  9. 【JSP】JSP的四种作用域
  10. java实心菱形_java打印出实心菱形与空心菱形
  11. 线程和进程有什么区别(简单介绍)
  12. tp3.2 执行原生sql
  13. 电脑内录录音软件,可选择录音来源
  14. [黑客入门全程图解].吴自容,武新华.等编著.文字版,精确还原
  15. 2019年最新,免费检测僵尸粉软件,无打扰检测清理微信僵尸粉
  16. 苹果iPad OS 16原生壁纸Mac动态桌面
  17. adobe绿色版cs6下载地址
  18. 渗透测试神器之metasploit
  19. AppleStore下载量查看
  20. 技巧|微信个性签名,汽车手动挡效果,你喜欢这样的吗?

热门文章

  1. 陕西活性炭需求分析_20212027年中国粉末活性炭行业市场发展现状调研与投资趋势前景分析报告...
  2. C++中如何区分引用和取地址符号?
  3. Nginx + CGI/FastCGI + C/Cpp(编不过去,不搞了。。。)(Common Gateway Interface)
  4. pycharm 无法导包、无法导入模块(模块名不能含有连接符“-”)
  5. Tensorfow_yolov3 Intel Realsense D435 图像整合(合并)输入GPU计算耗时测试
  6. python 多进程 multiprocessing 进程池pool报错 in join assert self._state in (CLOSE, TERMINATE) AssertionError
  7. Building Shops dp 预处理距离
  8. java zmq订阅_从ZMQ PUB套接字获取订户过滤器
  9. springboot打包发布
  10. springmvc静态资源拦截与访问