From: | Chapman Flack <chap(at)anastigmatix(dot)net> |
---|---|
To: | PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org> |
Subject: | Re: pow support for pgbench |
Date: | 2017-12-06 18:41:57 |
Message-ID: | 4e384467-f28a-69ce-75aa-4bc01125a39d@anastigmatix.net |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Raúl Marín Rodríguez <rmrodriguez(at)carto(dot)com> wrote:
> I don't want to go too deep into it, but you get stuff like this:
>
> Select pow(2.0, -3)::text = pow(2, -3)::text;
> ?column?
> ----------
> f
Indeed, to me, that has turned out to be the most intriguing part of
the whole thread. Needs to be in some SQL subtleties exam somewhere:
select pow(2.0,-3), pow(2,-3);
pow | pow
--------------------+-------
0.1250000000000000 | 0.125
Looks like the first call resolves to the numeric version, while
the second (with integer arguments) resolves to the double one:
select pow(2.0,-3) is of (numeric), pow(2,-3) is of (double precision);
?column? | ?column?
----------+----------
t | t
Still, a numeric 0.125 doesn't always have those trailing zeros:
select pow(2.0,-3), pow(2,-3)::numeric;
pow | pow
--------------------+-------
0.1250000000000000 | 0.125
What's going on in the representation?
select numeric_send(pow(2.0,-3)), numeric_send(pow(2,-3)::numeric);
numeric_send | numeric_send
------------------------+------------------------
\x0001ffff0000001004e2 | \x0001ffff0000000304e2
I assume the 10 vs. 03 hex in the tails of those things represent
either 'precision' or 'scale' of 16 vs. 3? I don't get much help
from IS OF (numeric(p,s)), which seems to ignore any p,s and just
be true for any numeric. But here, this matches:
select numeric_send(0.125::numeric(16,16));
numeric_send
------------------------
\x0001ffff0000001004e2
How does numeric_power choose the precision and scale of its result?
Is that something the standard dictates?
Given that 0.125 is exact for this answer, at first I wanted to
ask if numeric_power could be made to produce the result with
precision 3, but then I realized that's backwards. A result with
precision 3 would be like saying, eh, it's somewhere between
0.1245 and 0.1255. If a result is known to be exact, it would be
better to go the other way and return it as numeric(huge).
That then led me to wonder if the cast float8_numeric is really
doing the right thing. Is it turning 0.125 (an exact representation
as float8) into numeric(3,3), again hedging as if it might be anything
from 0.1245 to 0.1255? Would it be better for float8_numeric to
produce a numeric with the precision/scale reflecting the actual
limits of float8?
Ok, now I've been driven to UTSL. It looks as if the intent of
the snprintf(..., "%.*g", DBL_DIG, val) in float8_numeric could
have been to accomplish that. It doesn't, though, as (at least
on my platform), %g drops trailing zeros, though there
is a documented 'alternate form' flag # that prevents that.
It works in bash:
bash-4.2$ printf '%.*g\n' 15 0.125
0.125
bash-4.2$ printf '%#.*g\n' 15 0.125
0.125000000000000
Does the standard prescribe how cast(float8 as numeric) ought to
select the precision/scale?
Sorry to drift OT, as this is more about the SQL functions than
pgbench, but it was too puzzling to ignore. :)
-Chap
From | Date | Subject | |
---|---|---|---|
Next Message | Alexander Korotkov | 2017-12-06 18:49:53 | Re: compress method for spgist - 2 |
Previous Message | Tom Lane | 2017-12-06 17:57:26 | Re: pgsql: When VACUUM or ANALYZE skips a concurrently dropped table, log i |