【重学 MySQL】五十五、浮点和定点数据类型
在MySQL中,浮点和定点数据类型用于存储小数和实数。
种类
MySQL提供了两种主要的浮点数据类型:FLOAT和DOUBLE,以及一种定点数据类型DECIMAL。
- FLOAT:单精度浮点数,占用4个字节的存储空间。它可以表示的数值范围大约是-3.402823466E+38到-1.175494351E-38,以及0和1.175494351E-38到3.402823466E+38。FLOAT类型通常用于存储精度要求不是特别高的小数,如商品价格等。
- DOUBLE:双精度浮点数,占用8个字节的存储空间。它可以表示的数值范围大约是-1.7976931348623157E+308到-2.2250738585072014E-308,以及0和2.2250738585072014E-308到1.7976931348623157E+308。DOUBLE类型具有更高的精度和更大的范围,适用于科学计算等需要高精度的数值场景。
- DECIMAL:定点数类型,用于存储具有固定精度和小数位数的数值。DECIMAL类型的精度由用户定义,可以指定总的数字位数(M)和小数点后的数字位数(D)。DECIMAL类型在存储时不会发生任何近似或舍入错误,因此适用于财务和精确计算等场景。
选择
在选择浮点数据类型时,需要考虑以下因素:
- 精度要求:根据数据的精度要求选择合适的浮点和定点数据类型。如果精度要求不是特别高,可以选择FLOAT类型;如果精度要求较高,可以选择DOUBLE类型;如果需要固定精度和小数位数,可以选择DECIMAL类型。
- 存储范围:根据数据的存储范围选择合适的浮点和定点数据类型。如果数据范围较小,可以选择FLOAT类型;如果数据范围较大,可以选择DOUBLE类型。
- 性能:在处理大量数据时,较小的浮点和定点数据类型(如FLOAT)通常具有更好的性能。然而,如果精度和范围是关键因素,可能需要选择较大的浮点和定点数据类型(如DOUBLE)或定点数据类型(如DECIMAL)。
- 应用场景:根据应用场景选择合适的浮点和定点数据类型。例如,在存储商品价格时,可以选择FLOAT类型;在进行科学计算时,可以选择DOUBLE类型;在处理财务和精确计算时,可以选择DECIMAL类型。
数据精度说明
浮点数据精度
浮点数据(如FLOAT、DOUBLE等)在计算机中采用科学记数法的方式存储,包括一个尾数(有效数字)和一个指数(表示小数点的位置)。浮点数的精度主要由尾数的位数决定。
-
单精度浮点数(float):
- 尾数通常为23位(IEEE 754标准),但由于有一个隐含的1位(即小数点左侧只能有1位,且必须为1),因此实际有效位数为24位。
- 在十进制中,这大约相当于7~8位有效数字。
-
双精度浮点数(double):
- 尾数通常为52位(IEEE 754标准),同样有一个隐含的1位,因此实际有效位数为53位。
- 在十进制中,这大约相当于15~16位有效数字。
浮点数的精度是有限的,因为计算机无法精确表示所有的小数。特别是那些无法被二进制完整表示的小数,计算机只能尽量用接近的值来表示,这就会导致精度误差。例如,0.1在二进制中无法被精确表示,因此使用二进制的计算机在存储和计算0.1时会存在精度问题。
定点数据精度
定点数据(如DECIMAL等)在计算机中采用固定小数点位置的方式存储,即小数点位置是固定的,不会随着数值的变化而变化。定点数的精度由其小数位数确定。
- 定点整数:小数点位置在数的最右侧,即没有小数部分。
- 定点小数:小数点位置在数的中间或左侧,具有固定的小数位数。
定点数的精度取决于用户定义的小数位数。例如,如果一个定点数被定义为具有4位小数,那么它就可以精确表示到小数点后第四位。由于定点数采用固定小数点位置的方式存储,因此它们可以精确表示指定精度范围内的小数数值,不会发生精度丢失。
总结
- 浮点数 :精度由尾数的位数决定,单精度浮点数大约具有7~8位有效数字,双精度浮点数大约具有15~16位有效数字。由于计算机无法精确表示所有的小数,因此浮点数在存储和计算时可能会存在精度误差。
- 定点数:精度由用户定义的小数位数确定。由于采用固定小数点位置的方式存储,因此定点数可以精确表示指定精度范围内的小数数值,不会发生精度丢失。
在选择数据类型时,应根据具体的应用场景和需求来选择合适的类型。如果需要高精度计算,并且对存储空间没有特殊要求,那么定点数是一个更好的选择。如果需要对大范围数值进行计算,并且对精度要求不是特别高,那么浮点数可能是一个更合适的选择。
精度误差说明
浮点数据精度误差
浮点数据(如FLOAT、DOUBLE等)在计算机中采用科学记数法表示,其精度误差主要来源于以下几个方面:
-
表示误差:
- 浮点数采用二进制表示,而某些十进制小数在二进制下无法精确表示,只能近似存储。这种近似表示会导致存储的数值与实际数值之间存在微小的差异,即表示误差。
-
舍入误差:
- 在进行浮点数运算时,由于计算机内部表示的局限性,运算结果通常会被舍入到最接近的可表示数值。这种舍入操作会引入一定的误差,即舍入误差。
-
累积误差:
- 在多次浮点数运算过程中,每次运算引入的微小误差可能会逐渐累积,导致最终结果与实际值之间存在较大的差异,即累积误差。这种误差在连续运算或复杂计算中尤为明显。
-
溢出和下溢:
- 浮点数表示的范围是有限的,当数值超过其表示范围时,会发生溢出(导致结果无法表示)或下溢(导致结果接近零但非零)。这两种情况都会导致精度损失。
定点数据精度误差
定点数据(如DECIMAL等)在计算机中采用固定小数点位置的方式存储,其精度误差相对较小,主要来源于以下几个方面:
-
表示精度:
- 定点数可以精确表示指定精度范围内的小数数值,不会发生表示误差。其精度由用户定义的小数位数确定。
-
舍入规则:
- 在进行定点数运算时,如果需要舍入操作,通常会遵循特定的舍入规则(如四舍五入、向下舍入等)。这些规则在一定程度上可以减小舍入误差,但无法完全消除。
-
溢出:
- 定点数同样存在溢出问题,当数值超过其表示范围时,会导致结果无法表示。然而,由于定点数通常用于表示有限范围内的数值,因此溢出问题相对浮点数来说不那么常见。
总结
- 浮点数:由于采用二进制表示和近似存储方式,浮点数在存储和计算时可能会引入表示误差、舍入误差和累积误差。这些误差在连续运算或复杂计算中尤为明显,可能导致最终结果与实际值之间存在较大差异。
- 定点数:由于采用固定小数点位置的方式存储和精确表示指定精度范围内的数值,定点数的精度误差相对较小。然而,在进行舍入操作或超出表示范围时,仍可能引入一定的误差。
在选择数据类型时,应根据具体的应用场景和需求来选择合适的类型。如果需要高精度计算和对存储空间没有特殊要求,那么定点数是一个更好的选择。如果需要对大范围数值进行计算或对精度要求不是特别高,那么浮点数可能是一个更合适的选择。
示例
以下是一些使用浮点和定点数据类型的示例:
sql
CREATE TABLE example (
id INT NOT NULL AUTO_INCREMENT,
price FLOAT(7,2) NOT NULL, -- 存储商品价格,最多7位数字,其中2位是小数
scientific_value DOUBLE NOT NULL, -- 存储科学计算值,使用双精度浮点和定点数
financial_value DECIMAL(10,2) NOT NULL, -- 存储财务数据,使用定点数类型,总共10位数字,其中2位是小数
PRIMARY KEY (id)
);
在上面的示例中,price
列使用了FLOAT类型来存储商品价格,scientific_value
列使用了DOUBLE类型来存储科学计算值,而financial_value
列则使用了DECIMAL类型来存储财务数据。
注意事项
- 精度损失:浮点和定点数据类型在存储和计算时可能会产生精度损失。因此,在需要高精度计算的场景中,应谨慎使用浮点和定点数据类型。
- 存储效率:浮点和定点数据类型占用的存储空间较大,可能会影响数据库的存储效率和性能。因此,在存储大量数据时,应合理选择浮点和定点数据类型以平衡精度和存储效率。
- 数据类型转换:在进行数据类型转换时,可能会导致精度损失或数据溢出。因此,在进行数据类型转换时,应确保目标数据类型能够容纳源数据类型的范围和精度。
综上所述,MySQL中的浮点和定点数据类型包括FLOAT、DOUBLE和DECIMAL三种类型。在选择浮点和定点数据类型时,需要考虑精度要求、存储范围、性能和应用场景等因素。合理使用浮点和定点数据类型可以提高数据库的存储效率和性能,同时满足数据的精度要求。
开发中经验
"由于 DECIMAL 数据类型的精准性,在我们的项目中,除了极少数(比如商品编号)用到整数类型外,其他的数值都用的是 DECIMAL,原因就是这个项目所处的零售行业,要求精准,一分钱也不能差。 " ------来自某项目经理