Eu encontrei o que parece ser uma perda de precisão inesperada ao converter de float4
diretamente para numeric
no PostgreSQL:
select 1079414::float4,
(1079414::float4)::numeric(15,2) as float4_to_numeric, -- loses precision
((1079414::float4)::float8)::numeric(15,2) as float4_to_float8_to_numeric;
Isso produz:
float4 | float4_to_numeric | float4_to_float8_to_numeric
------------+-------------------+----------------------------
1,079,414 | 1,079,410 | 1,079,414
A conversão direta de float4
para numeric
inesperadamente produz 1,079,410
em vez do esperado 1,079,414
.
A documentação do PostgreSQL afirma : "Em todas as plataformas suportadas atualmente, o real
tipo tem um intervalo de aproximadamente 1E-37 a 1E+37 com uma precisão de pelo menos 6 dígitos decimais." E percebo que são 7 dígitos decimais.
No entanto, a Wikipedia observa : "Qualquer número inteiro com valor absoluto menor que 2^24 pode ser representado exatamente no formato de precisão simples"
Como 1.079.414 é muito menor que 2^24 (16.777.216), eu esperaria que ele fosse representado exatamente.
Curiosamente, converter float8
primeiro para e depois para numeric
preserva o valor total, sugerindo que o PostgreSQL está armazenando a precisão total, mas de alguma forma a perde durante a conversão direta para numeric
.
Esse comportamento é um bug ou há alguma razão subjacente para esse comportamento? O que está acontecendo durante a conversão de tipo que causa essa perda de precisão?
Vejo que já existe uma pergunta semelhante , mas esse exemplo usa decimais, enquanto este é sobre um número inteiro menor que 2^24.