物理数据库设计 - 理解浮点数

一、浮点类型简介

  整型是一个很有用的数据类型,但只能存储整数,比如1、199、-19。但不能表述像2.5这样的浮点数。如果数据对精度要求很高,你需要使用另一种数据类型来取代整型。比如算钱的时候通常需要精确到小数点后两位,像$19.95。

  在这里首先来介绍下SQLServer中的浮点数:

浮点类型 是否精确 说明
decimal 精确数值型 -1038次方+1~1038-1的固定精度和范围的数值型数据
numeric 精确数值型 同decimal
float 近似数值型 -1.79E+308~1.79E+308之间的浮点数
real 近似数值型 -3.40E+38~3.40E+38之间的浮点数
money 货币型 -263~263-1的货币型数据,精确到万分之一
smallmoney 货币型 -214748.3648~214748.3647的货币型数据,精确到万分之一
  1. 在SQL Server中DECIMAL和NUMERIC这两者完全一样。
  2. 第一个参数是精度(数字总位数),第二个参数是刻度(小数点后的位数)。如NUMERIC(5,2)表示总长度5位,小数点后两位。
  3. 总长度与小数点后的位数比必须符合精度与刻度,不能多也不能少。
  4. DECIMAL与NUMERIC表示的是精确值,存进去的时候,存储的就是什么,而FLOAT与REAL存储的是近似数值,实际存储的值可能会比要存储的值稍大或者稍小。
  5. 在WHERE子句中,应该避免使用FLOAT或REAL列。
  6. SQL Server将精度和小数位数的每个特定组合看作是不同的数据类型。例如,decimal(5,5) 和 decimal(5,0) 被当作不同的数据类型。
  7. 从 decimal 或 numeric 向 float 或 real 转换会导致精度损失。从 int、smallint、tinyint、float、real、money 或smallmoney 向 decimal 或 numeric 转换会导致溢出。近损失精度SQL Server不报错,溢出的话,SQL Server会报错。
  8. SQL Server里使用MONEY和SMALLMONEY类型来表示货币类型,MONEY是8字节的,SMALLMONEY是4字节的。Money类型类似于DECIMAL(19,4);但是有不同,就是它的精度和刻度可以输入任意长度,不如DECIMAL类型限制得那么死。
  9. money 和 smallmoney 限制为小数点后有 4 位。如果需要小数点后有更多位,请使用 decimal 数据类型。
  10. money 或 smallmoney 常量中不允许使用逗号分隔符。只能在显式转换为 money 或 smallmoney 的字符串中指定逗号分隔符。
  11. SQL Server中的money,smallmoney,decimal,numeric对应C#中的decimal、float,real对应C#中的float。

二、反模式:使用FLOAT类型

  大多数编程语言都支持实数类型,使用关键字float或double。SQL也使用相同的关键字支持类似的数据类型。很多程序员很自然地就会在需要使用浮点数的地方使用SQL FLOAT类型,因为他们习惯与使用float类型编程。

  2.1 舍入的必要性

  并不是所有在十进制中描述的信息都能使用二进制存储。处于一些必要的因素,浮点数通常会舍入到一个非常接近的值。

  例如,1/3用一个无限循环的十进制可以表示为0.333...,真实的值无法完整地写出来,因为需要写无限多个3。小数点后数字的个数表示了这个数字的精确度,因此,无限循环地写下3,能够无限接近于1/3的精确值。

  在IEEE 754使用二进制表示浮点数。十进制中的无限小数在二进制中的表达方式是完全不同的。然而一些十进制的有限小数,比如59.95,在二进制中却需要表示为无限小数。FLOAT类型无法表达无限小数。因而,它存储了二进制表示中最接近59.95的值,用十进制表示可能等于59.950000762939。

  SELECT Num * 1000000000 FROM Number WHERE Id = 1

  返回值:59950000762.939

  对于某些运算来说,这样的误差还是不可容忍的。

  还有的例子就是用FLOAT进行比较操作

  SELECT * FROM Number WHERE Num = 59.95

  以上查询语句,可能会返回NULL。

  有时,对于下面的SQL语句,可能会返回正确的结果:

  SELECT * FROM Number ABS(Num - 59.95) < 0.000001

  但是再多一个0,精度要求更高的情况下,却不能够返回正确的结果:

  SELECT * FROM Number ABS(Num - 59.95) < 0.0000001

  非精确浮点数所累积的影响对于求和之外的合计运算来说会更大。虽然误差看起来非常小,但其累加起来的效果不可忽视。比如1*0.999一千次得到的结果是0.3677。这样执行的次数越多,误差就越大。

  2.2 识别反模式

  使用任何FLOAT、REAL或者DOUBLE类型的设计都可能是反模式,当应用程序使用的浮点数的取值范围并不需要达到IEEE754标准所定义的最大/最小值区间时,这样的设计并无不妥。比如,你只需要精确到小数点后3、4位,用Float类型并无不妥。

  其次,当你需要存储的数据的取值范围很大,大于INT和NUMERIC这两个类型所支持的范围时,FLOAT就是你的选择。科学计算类的程序就是FLOAT通常的应用场合。

三、解决方案:使用NUMERIC类型

  使用SQL中的NUMERIC或DECIMAL类型来代替FLOAT及其类似的数据类型进行固定精度的小数存储。

  ALTER TABLE NUMBER Add Num NUMERIC(9,2);

  这些数据类型精确地根据你定义的这一列时指定的精度来存储数据。通过类似于VARCHAR后面跟着长度的方式,将精度作为类型参数来定义列的类型。其精度指的是,在这一列中的每个值最多所能包含的有效数字的个数。9意味着你可以存储123456789。第二个参数指定其刻度。这里的刻度即指小数点后的位数。小数部分的数字也算在其有效位中,因此,精度9刻度2意味着可以存储1234567.89。小数点后面不能多也不能少,总位数不能多也不能少。

  这个时候,如果再将值按比例扩展十亿倍,就确定可以得到期望值:

  SELECT * FROM Number WHERE Num = 59.95

  59950000000。NUMERIC和DECIMAL这两个类型的行为是一样的,两者没有任何区别。

  如果你需要精确地表示十进制数,使用NUMERIC类型。FLOAT类型无法表示很多十进制的有理数,因此他们应该当成非精确值来处理。

时间: 2024-08-29 18:41:21

物理数据库设计 - 理解浮点数的相关文章

物理数据库设计 - 限定列的有效值

一.说明问题 其实这篇非常简单,因为大家都是用这个方法解决的,我决定用自己的语言来描述清楚这一个问题. 假设,我们有一个列,这个列只能够取某些有效值.比如一个用户表,我们有一个姓氏列,我们需要限定里面的值为中国的姓氏,比如:赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨. 二.反模式 对于这个问题,其实只有初学者可能会用这个方法,就是使用CHECK约束或者触发器来限定列的值,比如: CHECK (lastname IN ('赵','钱','孙','李')); 这样做的缺点如下: 1.获取所有可选值有困难,假设

物理数据库设计 - 文件是否应该存储在数据库中

多媒体文件已经广泛应用在很多程序当中.比如用户的头像,汽车的产品图片等等. 从我个人以往的经验来看,将文件的路径存储入数据库,然后文件本身存储于硬盘当中已是万年不变的解决方案. 其实,存储图片路径与存储图片文件本身,两种方案都有很好的立足点,但是大部分程序员都是将文件存储于数据库之外.虽然,这种方法没有什么大问题,但的确是存在一定的风险的. 一.问题描述 下面就来论述一下关于将文件存储于数据库外部的缺点. 1.垃圾回收问题. 当你想删除一张图片时,你只能够删除掉数据库中的记录,图片文件是没有办法

DBA词典:数据库设计常用词汇中英文对照表

1. Access method(访问方法):此步骤包括从文件中存储和检索记录. 2. Alias(别名):某属性的另一个名字.在SQL中,可以用别名替换表名. 3. Alternate keys(备用键,ER/关系模型):在实体/表中没有被选为主健的候选键. 4. Anomalies(异常)参见更新异常(update anomalies) 5. Application design(应用程序设计):数据库应用程序生命周期的一个阶段,包括设计用户界面以及使用和处理数据库的应用程序. 6. Att

SQL SERVER学习2——数据库设计

数据库设计是数据库知识中比较重要的部分,我们需要了解数据库设计的基本步骤,E-R图的画法. 数据库设计的基本概述 检验一个数据库设计好坏的标准就是,看他是否能够方便的执行各种数据检索和处理操作,并且有利于数据的控制管理和维护. 数据库设计步骤 设计数据库规范中比较著名的是"新奥尔良方法"(这个可不是做新奥尔良鸡腿的方法哦),Now Orleans,总计4个阶段: 需求分析(分析用户要求,制作数据流图和判定图) 概念结构设计(信息分析和定义,制作E-R图) 逻辑结构设计(设计实现,关系型

数据库设计(理解篇)

1. 原始单据与实体之间的关系(原始单据可以理解为整个录入界面的数据,这里的实体可以理解为基本表) 可以是一对一.一对多.多对多的关系. 在一般情况下,它们是一对一的关系:即一张原始单据对应且只对应一个实体(基本表). 在特殊情况下,它们可能是一对多或多对一的关系,即一张原始单证对应多个实体,或多张原始单证对应一个实体. 明确这种对应关系后,对我们设计录入界面大有好处. [例1]:一份员工履历资料,在人力资源信息系统中,就对应三个基本表:员工基本情况表.社会关系表.工作简历表.这就是“一张原始单

Hibernate为表字段添加备注信息,便于理解数据库设计

java实体类,可以加上字段的描述,是个好的习惯吧,便于理解数据库设计,为后期维护,升级,改造提供支持

数据库设计三范式理解

数据库设计的第三范式 关系数据库中的关系必须满足一定的要求.满足不同程度要求的为不同范式.数据库的设计范式是数据库设计所需要满足的规范.只有理解数据库的设计范式,才能设计出高效率.优雅的数据库,否则可能会设计出错误的数据库. 目前,主要有六种范式:第一范式.第二范式.第三范式.BC范式.第四范式和第五范式.满足最低要求的叫第一范式,简称1NF.在第一范式基础上进一步满足一些要求的为第二范式,简称2NF.其余依此类推. 范式可以避免数据冗余,减少数据库的空间,减轻维护数据完整性的麻烦,但是操作困难

数据库物理分布设计(转)

概述我们无论使用哪种数据库,无论怎样设计数据库,我想都会遵从一个原则:数据安全性和性能高效这两个主要方面,但是关于这两个方面的话题太多,在这里就不一 一陈述,我只是从数据库物理分布设计方面和大家一起简单的探讨一下.因为数据库良好的物理分布设计也是对数据安全性和性能高效影响比较大, 就象我们在建大楼之前一定要先打好地基一样.現实中我们在应用各种不同数据库的时候,往往会忽略数据库的物理布局,只有在数据库性能遇到问题的时候才去考虑,但这是得不偿失的,这样一来不仅会导致与 设计相关的问题出现,而且会影响

5-2数据库设计

5-2数据库设计 tags:数据库 基本步骤 步骤: 1. 需求分析阶段 进行数据库设计首先必须准确了解与分析用户需求.需求分析是整个设计过程的基础,是最困难和最耗费时间的一步. 2. 概念结构设计阶段 概念设计是整个数据库设计的关键,它通过对用户需求进行综合.归纳与抽象,行程一个独立于具体数据库管理系统的概念模型. 在概念结构设计阶段行程独立于机器特点,独立于各个关系数据库管理系统产品的概念模式,一般用ER图表示 3. 逻辑结构设计阶段 逻辑结构设计是将概念结构转为某个数据库管理系统所支持的数