
MySQL 浮点型和定点型可以用类型名称后加(M,D)来表示,M表示该值的总共长度,D表示小数点后面的长度,M和D又称为精度和标度,如float(7,4)的 可显示为-999.9999,MySQL保存值时进行四舍五入,如果插入999.00009,则结果为999.0001。
FLOAT和DOUBLE在不指 定精度时,默认会按照实际的精度来显示,而DECIMAL在不指定精度时,默认整数为10,小数为0。
1、CREATE TABLE test(f FLOAT(5,2) DEFAULT NULL,d DOUBLE(5,2) DEFAULT NULL,de DECIMAL(5,2) DEFAULT NULL)
2、DESC test
3、INSERT INTO test(f,d,de) VALUES(1.23,1.23,1.23)
数据插入都正确
4、INSERT INTO test(f,d,de) VALUES(1.234,1.234,1.23)
数据插入都正确,但是f和d由于标度的限制,舍去了最后一位。
5、INSERT INTO test(f,d,de) VALUES(1.234,1.234,1.234)
数据也插入成功,但是有一个警告提示:
1 queries executed, 1 success, 0 errors, 1 warnings
Note Code : 1265
Data truncated for column 'de' at row 1
6、将id1,id2,id3的精度和标度都去掉
ALTER TABLE test MODIFY f FLOAT
ALTER TABLE test MODIFY d DOUBLE
ALTER TABLE test MODIFY de DECIMAL
DELETE FROM test
DESC test
7、INSERT INTO test(f,d,de) VALUES(1.234,1.234,1.234)
1 queries executed, 1 success, 0 errors, 1 warnings
Note Code : 1265
Data truncated for column 'de' at row 1
f和d的数据正确插入,而de被截断。
浮点数如果不写精度和标度,则会按照实际显示,如果有精度和标度,则会将数据四舍五入后插入,系统不报错,定点数如果不设置精度和标度,刚按照默认的(10,0)进行 *** 作,如果数据超过了精度和标度值,则会警告!
同时,对数据求SUM()时会出现不同的结果,float和double求SUM都会出现很多小数点,而decimal求SUM得到的是精准数值:
8、INSERT INTO test(f,d,de) VALUES(1.234,0.01,1.23)
数据都插入成功
9、SELECT SUM(f),SUM(d),SUM(de) FROM test
理论上SUM(f)=3.698,SUM(d)=2.474,SUM(de)=3.46,但f,d都出现后面很长的一串浮点小数点。
谈谈个人理解,请带着怀疑和鉴别的角度去看待。1 先理解下定点数
--定义:
指规定小数点位置固定不变。
--存储:
* 在数据库或计算机中存储时,整数部分和小数部分分别使用一定的字节来存储(理解为分别用两部分字节来存储两个整数),小数点是作为存储属性存储的(如作为列类型时,小数点位置存储在表的定义部分),而不占用数据的存储字节。
* 定点数使用多少字节来存放数据,依赖于该数指定的精度(精度即为该数的总数字位数),总数字位数为小于2则使用1字节,为5-9位时用4字节,为19-38位时使用16字节(大部分数据库支持的最大就是38位数字);
--举例:
numeric(2,1),精度为2,使用1个字节来存放,存放数据范围为[-9.9, 9.9];如存储2.3时,在数据库存储为00100011,而小数位置固定在第四位前,这是由定义列时指明的;
--说明:
定点数存储精确的数字,numeric(2,1)就只能[-9.9, 9.9]之间的数,存的不是近似数(因为两部分都作为整数存储);当你在numeric(2,1)中存储2.33时,实际发生了隐式转换,实际存储为9.3(注意这并不是近似);
2 再来理解浮点数
--定义:
指采用浮点数表达方式来表示数据,这种表达方式利用科学计数法来表达实数,即用一个尾数(Mantissa ),一个基数(Base),一个指数(Exponent)以及一个表示正负的符号来表达数据,比如 123.45 用十进制科学计数法可以表达为 1.2345 × 10^2,其中 1.2345 为尾数,10 为基数,2 为指数。称其为浮点数就是因为利用指数达到了浮动小数点的效果。
--存储:
浮点数一般是使用IEEE规定的方式,即 对于单精度浮点数用1bit来存储符号位(正负号),8bit来存储指数,23bit来存储尾数;而且要求尾数的整数部分为1(注意,指二进位格式的,如1.01001),而且是使用二进位来保存,即基数为2;
在大多数数据库或计算机中存储时,单精度使用4字节,双精度使用8字节保存;
--举例:
二进制的 1001.101(对应于十进制的 9.625)可以表达为 1.001101 × 2^3,存储时符号位+存储为0,指数3存储为00000011,尾数1.001101存储为0011010000..(总共23位,去掉了小数点前的1,IEEE就是这样要求的);
--近似的产生:
因为我们使用的是十进制数,而计算机要转换为对应的二进制形式,由于有限的2进制位数表示的小数值不能和十进制一一对应(换句话说,十进制小数转为二进制可能变为无限小数而导致不精确 ),如2^-1对应0.5,2^-2对应0.25,2^-3对应0.125,因此对于像十进制的0.4(小数的末尾一位数不为5的)则不能精确存储;
--因近似引起的问题:
create table t (a float, b float)insert into t values(0.11, 0.04), (0.04, 0.11)
select * from t查询时显示正常,实际底层存储时发生了近似(十进制转换为二进制),而显示时又发生了近似(二进制转换为十进制);
select sum(a) from t查询显示 0.14999999850988388 ,为什么不是0.15的原因也就不言而喻了。
这也就是浮点数在损失精度、计算和比较要格外注意的事项;
3 总结
定点数,能存储精确数字,但保存的数据范围受了严格限制,格式也比较僵硬(这既是好处,也是坏处);
浮点数,不能存储精确数字,在小数的末尾一位数不是5(一直乘2不能圆整)的情况下会发生存储的近似处理;但可存储的数据范围更大;
sum函数在数据库是number类型的,你的代码中可以使用任何装的下数字型都可以接收。如:sum的值小于java中int的最大值,你就可以用int接收;如果大于Int的最大值而小于double的最大值,你就可以用double。一般在程序设计时,如果不确定它的值范围,可以用long型接收。欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)