Postgresql中精确浮点类型decimal和不精确浮点类型real(案例)

Postgresql提供四类浮点型,按功能看可以分成两类:

  • 精确型:decimal、numeric
  • 不精确型:real、double precision(float等价于double precision)

https://www.postgresql.org/docs/14/datatype-numeric.html
在这里插入图片描述

为什么说不精确呢?因为数据类型成功插入后,查询出来值可能和你插入的值不一样,原因是长度截断和四舍五入。
精确类型不会发生截断且如果超长了直接报错,主要插入成功了,查出来的一定等于插入的结果。

看下具体例子:

real:【不精确类型】【定长类型】PG10:六位有效数字,会四舍五入(PG14八位有效数字)

create table f1 (a real);
insert into f1 values (1.23456789);
insert into f1 values (1234.23456789012345);
insert into f1 values (123456.23456789);
insert into f1 values (123456.23456789012345);
select * from f1;
    a    
---------
 1.23457
 1234.23
  123456
  123456

double:【不精确类型】【定长类型】PG10:十五位有效数字,会四舍五入(PG14十七位有效数字)

create table f2 (a double precision);
insert into f2 values (123456789.123456789);
insert into f2 values (1.1234567890123456789);
insert into f2 values (12345678901234567890.1234567890123456789);
select * from f2;
          a           
----------------------
     123456789.123457
     1.12345678901235
 1.23456789012346e+19

create table f3 (a float);
insert into f3 values (123456789.123456789);
insert into f3 values (1.1234567890123456789);
insert into f3 values (12345678901234567890.1234567890123456789);
select * from f3;
           a            
------------------------
     123456789.12345679
     1.1234567890123457
 1.2345678901234567e+19

关于float(n)的写法:
PostgreSQL还支持 SQL 标准表示法float和float§用于声明非精确的数字类型。在这里,p指定以二进制位表示的最低可接受精度。 在选取real类型的时候,PostgreSQL接受float(1)到float(24),在选取double precision的时候,接受float(25)到float(53)。在允许范围之外的p值将导致一个错误。没有指定精度的float将被当作是double precision。

decimal / numeric:【精确类型】【变长类型】不会四舍五入,最高小数点前131072位,以及小数点后16383位,超出报错:ERROR: value overflows numeric format

create table f3 (a decimal);
insert into f3 values (123456789.123456789);
insert into f3 values (1.1234567890123456789);
insert into f3 values (12345678901234567890.1234567890123456789);
insert into f3 values (12345678901234567890.12345678901234567890123456789012345678901234567890);
select * from f3;
                                   a                                    
------------------------------------------------------------------------
                                                    123456789.123456789
                                                  1.1234567890123456789
                               12345678901234567890.1234567890123456789
 12345678901234567890.1234567890123456789012345678901234567890123456789

从存储角度看,real、double是定长类型,decimal / numeric是变长类型。

在构造tuple时,计算数据长度会走不同分支:
《Postgresql源码(58)元组拼接heap_form_tuple剖析》

	real类型长度计算:定长计算方法
		heap_compute_data_size
			data_length = att_align_datum(data_length, atti->attalign, atti->attlen, val);
			data_length = att_addlength_datum(data_length, atti->attlen, val);
 
	decimal类型长度计算:变长计算方法
		heap_compute_data_size
			if (ATT_IS_PACKABLE(atti) && VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
				data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高铭杰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值