From: | Bruce Momjian <bruce(at)momjian(dot)us> |
---|---|
To: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> |
Cc: | Noah Misch <noah(at)leadboat(dot)com>, David Rowley <dgrowleyml(at)gmail(dot)com>, PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org> |
Subject: | Re: Zero-padding and zero-masking fixes for to_char(float) |
Date: | 2015-03-23 15:33:22 |
Message-ID: | 20150323153322.GA18198@momjian.us |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
On Mon, Mar 23, 2015 at 12:36:25AM -0400, Tom Lane wrote:
> Bruce Momjian <bruce(at)momjian(dot)us> writes:
> > On Sun, Mar 22, 2015 at 12:46:08PM -0400, Noah Misch wrote:
> >> I recommend adding a "configure" test to use our snprintf.c replacements if
> >> sprintf("%.*f", 65536, 99999999999.0) gives unexpected output.
>
> > Do we really want to go to our /port snprintf just to handle 512+
> > digits?
>
> I'd rather not go that direction (that is, to using a configure test).
> It assumes that all copies of libc on a particular platform behave the
> same, which seems like a bad bet to me. I think we'd be better off to
> avoid asking libc to do anything that might not work everywhere.
>
> On the other hand, this line of thought might end up having you
> reimplement in formatting.c the same logic I put into snprintf.c
> recently, which seems a bit silly.
If we can't trust libc for 512+ precision (and I don't think a startup
check is warranted), I think we should either use our internal snprintf
for to_char() in all cases, or in cases where the precision is 512+. Of
course, this hinges on the assumption that only to_char() cares about
512+ digits --- if not, a startup check seems a requirement.
However, even if we have a working snprintf, the bigger problem is
having to do rounding, e.g. this is the worst case:
SELECT to_char(float4 '5.5555555555555555555555555555', '9D' || repeat('9', 1000) || 'EEEE');
What we have to do here is to round to the specified precision, i.e. we
can't just pad with zeros, which was my original approach. I am afraid
that means we have to keep the odd coding where we call snprintf with
zero decimal digits, get its length, then figure out the decimal
precision, then call snprintf again to format the string with rounding.
Then, we need to separate the mantissa from the exponent and add the
desired number of zeros and copy it into a new longer string.
So, instead of the code being cleaner, it will be even more messy, and
will duplicate some of what we already do in our port/snprintf.c.
Unfortunately, there is no way to call snprintf and tell it we want a
specific number of decimal digits _and_ pad the rest with zeros. I
think trying to do the rounding on the output string will never work
well, e.g. 9.9999 rounded to one decimal digit is 10.0.
Yuck.
--
Bruce Momjian <bruce(at)momjian(dot)us> http://momjian.us
EnterpriseDB http://enterprisedb.com
+ Everyone has their own god. +
From | Date | Subject | |
---|---|---|---|
Next Message | Tom Lane | 2015-03-23 15:34:21 | Re: Table-level log_autovacuum_min_duration |
Previous Message | Tom Lane | 2015-03-23 15:33:12 | Re: Order of enforcement of CHECK constraints? |