Vi algumas perguntas relacionadas, mas nenhuma deu uma resposta satisfatória para isso.
select
((5999.999999999999)::numeric) as num,
((5999.999999999999)::float8) as f64,
((5999.999999999999)::float8)::numeric as f64_to_num,
((5999.999999999999)::numeric)::float8 as num_to_f64;
num | f64 | f64_to_num | num_to_f64
-------------------+-------------------+------------+-------------------
5999.999999999999 | 5999.999999999999 | 6000 | 5999.999999999999
(1 row)
Isso é surpreendentemente inconsistente, porque um número que é representado no mesmo lugar em numeric e float8, eu não esperaria que ele fosse arredondado para cima ao converter.
O que está errado?
A conversão de
float8
(double precision
) paranumeric
é realizada pela função PostgreSQLfloat8_numeric()
. Essa função usasnprintf()
para converter o valor de ponto flutuante para uma string com uma precisão deDBL_DIG
:O resultado é então convertido para um arquivo
numeric
.Agora
DBL_DIG
é 15 no meu sistema Linux, e 5999,999999999999 arredondado para uma precisão de 15 é 6000.Esse comportamento é controlado pela
extra_float_digits
configuração.tentar
set extra_float_digits to 0;