环境:
- window10
- vs2022
- .net 6
- mysql 8.0.25
- DBeaver
1. float和double类型
在mysql中,float和double都是浮点数类型:
- float 占4个字节,精度是6位;
- double 占8个字节,精度是16位;
它们的性质和c#中浮点数的性质是一样的,只不过精度要求的更严格和明确一些;
参照:c#中浮点型的精度要求为
测试mysql中的float和double:
create table test(
t_float float,
t_double double
)
insert into test.test (t_float) values(123456);-- 正常
insert into test.test (t_float) values(1234567);-- 四设五入 1234570
insert into test.test (t_float) values(12345678901);-- 失真 12345700352
insert into test.test (t_float) values(12345.6); -- 正常
insert into test.test (t_float) values(12345.62); -- 四设五入 12345.6
insert into test.test (t_float) values(123.123); -- 正常
insert into test.test (t_float) values(12.1234); -- 正常
insert into test.test (t_float) values(1.12345); -- 正常
insert into test.test (t_float) values(1234.1234); -- 四设五入 1234.12
-- double
insert into test.test (t_double) values(1234567890123456);-- 正常
insert into test.test (t_double) values(12345678901234567);-- 四设五入 12345678901234568
insert into test.test (t_double) values(123.12345678901);-- 正常
insert into test.test (t_double) values(1234567890.123456);-- 正常
select * from test
输出如下:
我们可以认为是这样的:
当我们把数据插入float类型时,mysql会优先保留6位有效数字,对右侧的数字进行四舍五入;
当我们把数据插入double类型时,mysql会优先保留16位有效数字,对右侧的数字进行四设五入;
注意:mysql不会因为数据超范围而报错,比如:
12345678901
远超精度,但它只会数据失真并不会报错。
2. float和double语法
推荐的使用方法是:t_float float
、t_double double
,即:不添加其他参数。
但为了兼容sql标准,mysql中提供:float(p)
这种写法,这里的p取值范围是:[0,53],超过范围会报错,另外:这里的p仅用来决定mysql内部采用float
还是double
存储,当p∈[0,23] 时,mysql采用float存储,当p∈[24,53]时,mysql采用double存储。
3. float和double的非推荐用法
上面说的是推荐用法,在推荐用法中mysql的float和c#的float行为表现基本一致。
还有非标准用法,比如:float(M,D)
,不过这种写法即将被弃用了。
虽然是被弃用,但它好像也并非一无是处:
float(M,D)中的M
表示总有效数字,D
表示小数位数。这有点像decimal(M,D)
的M和D。
如果我们定义:float(5,2)
的话,就表示:小数点后最大2位,小数点前最大3位,小数点前超过3位将报错,小数点后超过2位将四舍五入;
测试如下:
create table test(
t_float5_2 float(5,2)
)
insert into test.test (t_float5_2) values(123.12);-- 正常
insert into test.test (t_float5_2) values(1234.1);-- 报错: Out of range value
insert into test.test (t_float5_2) values(1.1234);-- 四设五入 1.12
select * from test
输出如下:
可以看到这种非标准用法限制更严格一点,不过因为它即将被启用,不做过多探索。
另外,double类型没有非标准的 double(M,D) 写法!
另外,除了float(M,D)还有real(M,D)和double precision(M,D)。
这里总结下它们的用法和区别:
4. c#中使用方式
由于mysql中的float和double都是浮点型数据,基本和c#中的float和double一一对应,所以在c#中我们完全可以使用float和double分别去替代,但一般我们在c#中会统一使用double,如下:
public class Model
{
public double? t_float { get; set; }
public double? t_double { get; set; }
}
5. 最后看下它们的元数据
create table test(
t_float float,
t_float7 float(7),
t_float10 float(10),
t_float35 float(35),
t_float40 float(40),
t_double double,
-- t_double double(5), -- 报错
t_float7_5 float(7,5), -- 弃用
t_real real,
t_real7_5 real(7,5),
t_double_precision8_5 double precision(8,5)
)
select c.TABLE_SCHEMA ,c.TABLE_NAME ,c.COLUMN_NAME ,c.ORDINAL_POSITION,c.DATA_TYPE,c.NUMERIC_PRECISION ,c.COLUMN_TYPE ,c.NUMERIC_SCALE
from information_schema.`COLUMNS` c where TABLE_SCHEMA ='test' and TABLE_NAME ='test' order by ORDINAL_POSITION