MySQl的float问题汇总
发现了一个比较奇特的问题!
表结构如下:
CREATE TABLE `test` (
`id` int(10) unsigned NOT NULL auto_increment,
`user_id` int(10) unsigned NOT NULL default '0',
`result` float NOT NULL default '0',
`times` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`id`))
记录如下
1,123,2.01,...
2,888,2.52,...
.......
执行select * from test where result=2.52
结果为空集;
再执行select * from test where result="2.52"
还是空集
假设table中有一个price=28.8的记录(price为float型),那么你用
Sql代码 复制代码
1. select * from table where price=28.8
是有可能select不到这条记录的,因为10进制和2进制之间的误差,这个28.8有可能是28.7999999
到目前为止我想到是有两个方案:
一个是这样select(其实在对精准要求比较高的情况下,这样可能是有问题)
select * from table where price>28.7 and price<28.9
2.还有一个是在设计的时候比较fancy的解决方案(号称google是这样搞的):
根本不设计float型的字段,而是用一个int型+标识这个int型的小数位来代替float型,也就是price=28.8在数据库中存的是price=288,precision=1
但是
以上方法有缺陷,第一个方法大多用户估计行不通,精度不一样。不太好控制
第二个方法设计确实比较有技巧,但是无法在MySQL中简单的进行排序。
而我的需求即是又要能排序,又要可以使用where result=2.52
我想了第三种方法,就是再增加一个字段
执行alter table test add cresult varchar(32) not null;即可
这样当我要执行排序操作时
select * from test order by result desc;
执行开头那个例子时
select * from test where cresult="2.52"
二个字段分工不同。
当然我也想到了第四种方法,但适用范围小,是有前提的。
即result里面的值必须固定长度
比如22.98,即小数点前和小数点后都必须为n位数,也就是说范围从00.00-99.99
或者000.000-999.999
第一类00.00-99.99以小数点为分隔,看此小数看成100进制,假设数为12.23,那么12*(100的1次方)+23*(100的0次方),结果为一整型
第二类同理,看成1000进制。
当需要知道真实值时把100或1000进制转换一下即可得到原始值。
这样把转换后的值存入result里(此时result为int型),即可排序又可where result=计算后的值