zoukankan      html  css  js  c++  java
  • sqlserver中的小数类型(float和decimal)

    在SQL Server中实际上只有两种小数数值类型,分别是float(近似数值)decimal(精确数值),这两种类型能表示所有的小数数值类型。

    float(近似数值类型)

    float表示的是近似数值,存在一定的精度缺失。

    float(n)

    这里的n是以科学计数法存储浮点数尾数的位数,因此此参数决定了精度和存储的大小。其是可选的,默认值是53,即float等价于float(53),占用8bytes。如果指定了n,则它必须是介于1至53之间的值。实际上,虽然n的取值范围定义是1至53,但实际上float只能表示float(53)和float(24)两种类型,分别占用8bytes和4bytes。

    n的范围

    精度

    存储大小

    1-24(都视为24)

    7位小数

    4bytes 

    25-53(都视为53)

    15位小数

    8bytes    

    使用近似数值要格外注意尽量避免相等比较,因为比如1可以被存储为1.000000056,也可以被存储为1.00000000672,进行相等比较会得到意料之外的结果。

    decimal(精确数值类型)

    decimal表示的是精确数值类型。不存在精度损失,别名是numeric。

    decimal(p, s)
    -- 等价于
    numeric(p, s)

    精确数值类型需要分别指定小数的最大位数(p)和小数位的数量(s):

    • p(precision):指定小数的最大位数,小数点的左侧和右侧的数字的总数量不能超过p,p的取值范围是从1到38,默认值为18。
    • s(scale):指定在小数点右侧的小数位数,p-s是小数点左边的最大位数。s必须是从0到p的值,只有在指定了精度的情况下才能指定s,s的默认值是0,因此,0 <= s <= p。 

    p的大小也同时决定了存储位数的大小:

    精度大小

    存储位数

    1-9

    5

    10-19

    9

    20-28

    13

    29-38

    17

    因为p和s必须遵守规则:0 <= s <= p <= 38,所以decimal(p, s)实际上能够表示的有效值是从-10^38+1到10^38-1。这就意味着,decimal数据类型的最大精度是38,即最多可以存储38位数字,所有这些数字均可位于小数点后面。decimal数据类型存储精确的数字表示形式,没有近似值。

    小数的除法

    小数的除法实际上是近似运算,因此在使用除法的时候SQL Server会自动将小数的类型提升为float类型(隐式数据类型升级)。

    小数常量的默认数据类型是decimal,但是float类型的优先级比decimal类型要高。在默认的情况下,SQL Server会将小数数值的常量自动转换为decimal数据类型(常态下),而在进行小数的除法运算的时候,则会就近进行数据类型的升级,转换为float(24)或float(53)数据类型(运算时)。

    简单举个例子,常量12.345在常态下会被解析并转换为numeric(5, 3)的数值类型,即使用最小精度5和最小小数位数3;而在运算除法时,比如12.345/2则会被解析并转换为float(24),即最小精度的近似数值类型。

    小数转为字符串

    相比cast(float_expression as float(24/53)),使用str()函数更能够有效控制近似数值的小数位数,因为str()函数获取的是近似数值。

    str(float_expression [ , length [ , decimal ] ])

    str()函数可以接受length、decimal两个参数,皆是可选的。

    • length是小数的总位数,包含正负符号,小数点,小数点左边和右边数字个数之和;
    • decimal是小数位的数量(小数点右边数字个数),小数位最大为16位,不能超过16,否则,会被截断为16位。如果小数位没有decimal多,那么右边补0。
    • 返回值是varchar类型。

    将decimal常量转换为varchar类型:

    select str(123.45, 10, 2); -- 123.45

    将float表达式的值转换为varchar类型(位数不足自动补0):

    select str(1.0/3, 10, 8); -- 0.33333300

    对小数常量转换为varchar类型,减少小数位的数量,由2位减少为1位(会自动进行四舍五入运算):

    select str(123.45, 6, 1); -- 123.5

    使用函数str或cast将float和decimal强制转换为varchar类型时,返回的数值可能是不相同的:

    select str(56.64564684439527, 38, 20); -- 56.64564684438742000000
    select cast(56.64564684439527 as varchar(100)); -- 56.64564684439527

    这是因为两种函数的处理方式的不同导致的:str()函数会对小数数值先取近似值;而cast()函数则是返回与原始值数据类型相同的值(decimal返回精确值,float返回近似值)。

    "我终于没能留下你渐行渐远的脚步。"

  • 相关阅读:
    NTP on FreeBSD 12.1
    Set proxy server on FreeBSD 12.1
    win32 disk imager使用后u盘容量恢复
    How to install Google Chrome Browser on Kali Linux
    Set NTP Service and timezone on Kali Linux
    Set static IP address and DNS on FreeBSD
    github博客标题显示不了可能是标题包含 特殊符号比如 : (冒号)
    server certificate verification failed. CAfile: none CRLfile: none
    删除文件和目录(彻底的)
    如何在Curl中使用Socks5代理
  • 原文地址:https://www.cnblogs.com/yanggb/p/12702975.html
Copyright © 2011-2022 走看看