BUG #4660: float functions return -0

Started by ITAGAKI Takahiroalmost 17 years ago9 messages
#1ITAGAKI Takahiro
itagaki.takahiro@oss.ntt.co.jp

The following bug has been logged online:

Bug reference: 4660
Logged by: ITAGAKI Takahiro
Email address: itagaki.takahiro@oss.ntt.co.jp
PostgreSQL version: 8.3.3
Operating system: Fedora 8
Description: float functions return -0
Details:

Float8 versions of trunc(), ceil() and round() could return -0 on some
version of glibc.

We avoid -0 in float8um (unary minus),
but should we add the same codes in those functions?
There is inconsistency compared with numeric version
of funcs and it is a platform-dependent behavior;
0 is returned there.

postgres=# SELECT pg_catalog.trunc((-0.1)::float8);
trunc
-------
-0
(1 row)

postgres=# SELECT pg_catalog.ceil((-0.1)::float8);
ceil
------
-0
(1 row)

postgres=# SELECT pg_catalog.round((-0.1)::float8);
round
-------
-0
(1 row)

postgres=# select version();
version
----------------------------------------------------------------------------
------------------------
PostgreSQL 8.3.3 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 4.1.1
20070105 (Red Hat 4.1.1-51)
(1 row)

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: ITAGAKI Takahiro (#1)
Re: BUG #4660: float functions return -0

"ITAGAKI Takahiro" <itagaki.takahiro@oss.ntt.co.jp> writes:

We avoid -0 in float8um (unary minus),

I wonder why we do that.

regards, tom lane

#3ITAGAKI Takahiro
itagaki.takahiro@oss.ntt.co.jp
In reply to: ITAGAKI Takahiro (#1)
Re: [BUGS] BUG #4660: float functions return -0

I reported the following bug to -bugs, and I'd like to discuss
whether we need to fix the issue or how to fix it.

"ITAGAKI Takahiro" <itagaki.takahiro@oss.ntt.co.jp> wrote:

Bug reference: 4660
PostgreSQL version: 8.3.3
Operating system: Fedora 8
Description: float functions return -0
Details:
Float8 versions of trunc(), ceil() and round() could return -0 on some
version of glibc.

postgres=# SELECT pg_catalog.trunc((-0.1)::float8);
-0
postgres=# SELECT pg_catalog.ceil((-0.1)::float8);
-0
postgres=# SELECT pg_catalog.round((-0.1)::float8);
-0

We already have some codes to avoid -0 float8um (unary minus),
but there are no protection in trunc(), ceil() and round() at least.
It is platform-dependent behavior (msvcrt doesn't return -0), and there is
a difference between float8 and numeric (numeric doesn't support -0).

1. Remove 'avoid -0' from float8um because -0 is a possible value
for floating point numbers.
2. Add 'avoid -0' codes to those functions.
(Are there any places where we also add it?)
3. Move 'avoid -0' codes to float8out() and float8send().
'-0' could be stored in database, but users receives only '+0'.

Fixes might be needed by float4 versions.
I'll write a patch when we come to a decision.

Regards,
---
ITAGAKI Takahiro
NTT Open Source Software Center

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: ITAGAKI Takahiro (#3)
Re: [BUGS] BUG #4660: float functions return -0

ITAGAKI Takahiro <itagaki.takahiro@oss.ntt.co.jp> writes:

We already have some codes to avoid -0 float8um (unary minus),
but there are no protection in trunc(), ceil() and round() at least.

I looked into the CVS history to find out when the anti-minus-zero code
got put into float8um. It seems to have been done by Tom Lockhart here:

http://anoncvs.postgresql.org/cvsweb.cgi/pgsql/src/backend/utils/adt/float.c.diff?r1=1.13;r2=1.14

The CVS commit message says
Check for zero in unary minus floating point code (IEEE allows an
explicit negative zero which looks ugly in a query result!).
along with some other unrelated changes. I can find no evidence in the
mailing list archives that there was any discussion about the point,
so I think Tom did that on his own authority.

I'm of the opinion that minus zero was put into the IEEE floating point
standard by people who know a great deal more about the topic than
anyone on this list does, and that we do not have the expertise to be
second-guessing how it should work. Not long ago we took out code that
was interfering with spec-compliant treatment of IEEE infinity; I think
we should take out this code too.

Yes, it will be platform dependent, because various platforms get the
IEEE spec wrong to some degree, but so what? This is hardly the only
platform dependence of that kind.

regards, tom lane

#5Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#4)
Re: [BUGS] BUG #4660: float functions return -0

Tom Lane wrote:

ITAGAKI Takahiro <itagaki.takahiro@oss.ntt.co.jp> writes:

We already have some codes to avoid -0 float8um (unary minus),
but there are no protection in trunc(), ceil() and round() at least.

I looked into the CVS history to find out when the anti-minus-zero code
got put into float8um. It seems to have been done by Tom Lockhart here:

http://anoncvs.postgresql.org/cvsweb.cgi/pgsql/src/backend/utils/adt/float.c.diff?r1=1.13;r2=1.14

The CVS commit message says
Check for zero in unary minus floating point code (IEEE allows an
explicit negative zero which looks ugly in a query result!).
along with some other unrelated changes. I can find no evidence in the
mailing list archives that there was any discussion about the point,
so I think Tom did that on his own authority.

I'm of the opinion that minus zero was put into the IEEE floating point
standard by people who know a great deal more about the topic than
anyone on this list does, and that we do not have the expertise to be
second-guessing how it should work. Not long ago we took out code that
was interfering with spec-compliant treatment of IEEE infinity; I think
we should take out this code too.

Yes, it will be platform dependent, because various platforms get the
IEEE spec wrong to some degree, but so what? This is hardly the only
platform dependence of that kind.

Agreed.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +

#6Gregory Stark
stark@enterprisedb.com
In reply to: Tom Lane (#4)
Re: [BUGS] BUG #4660: float functions return -0

Tom Lane <tgl@sss.pgh.pa.us> writes:

The CVS commit message says
Check for zero in unary minus floating point code (IEEE allows an
explicit negative zero which looks ugly in a query result!).

I'm of the opinion that minus zero was put into the IEEE floating point
standard by people who know a great deal more about the topic than
anyone on this list does, and that we do not have the expertise to be
second-guessing how it should work. Not long ago we took out code that
was interfering with spec-compliant treatment of IEEE infinity; I think
we should take out this code too.

If the original complaint was that it looked ugly in query results then the
right way to fix it would surely in float4out and float8out. Interfering with
IEEE floating points may be a bad idea but surely it's up to us how we want to
represent those values in text.

But without a convenient and widely used binary format that kind of restricts
our options. If we squash -0 on float[48]out then dumps will lose information.
So I guess there's nothing we can do about it now. I wonder if we're going to
find users complaining about things like "displaying -0 matching results"
though...

--
Gregory Stark
EnterpriseDB http://www.enterprisedb.com
Ask me about EnterpriseDB's Slony Replication support!

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Gregory Stark (#6)
Re: [BUGS] BUG #4660: float functions return -0

Gregory Stark <stark@enterprisedb.com> writes:

Tom Lane <tgl@sss.pgh.pa.us> writes:

I'm of the opinion that minus zero was put into the IEEE floating point
standard by people who know a great deal more about the topic than
anyone on this list does, and that we do not have the expertise to be
second-guessing how it should work. Not long ago we took out code that
was interfering with spec-compliant treatment of IEEE infinity; I think
we should take out this code too.

If the original complaint was that it looked ugly in query results then the
right way to fix it would surely in float4out and float8out. Interfering with
IEEE floating points may be a bad idea but surely it's up to us how we want to
represent those values in text.

But without a convenient and widely used binary format that kind of restricts
our options. If we squash -0 on float[48]out then dumps will lose information.

The point I'm trying to make is that we should deliver IEEE-compliant
results if we are on a platform that complies with the spec. Right down
to the minus sign. If that surprises people who are unfamiliar with the
spec, well, there are a lot of things about floating point arithmetic
that surprise people who aren't familiar with it.

regards, tom lane

#8Brendan Jurd
direvus@gmail.com
In reply to: Tom Lane (#7)
Re: [BUGS] BUG #4660: float functions return -0

On Wed, Feb 18, 2009 at 2:57 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

The point I'm trying to make is that we should deliver IEEE-compliant
results if we are on a platform that complies with the spec. Right down
to the minus sign. If that surprises people who are unfamiliar with the
spec, well, there are a lot of things about floating point arithmetic
that surprise people who aren't familiar with it.

Agreed. There are plenty of things about floats that are downright
wonky, and when people start seeing minus zero in their float
computations it might prompt them into doing some reading, and
figuring out that what they really wanted was numeric.

(not saying that floats are without application, but I've often
encountered them in places they ought not to be)

Cheers,
BJ

#9Tom Lane
tgl@sss.pgh.pa.us
In reply to: Brendan Jurd (#8)
Re: [BUGS] BUG #4660: float functions return -0

Brendan Jurd <direvus@gmail.com> writes:

On Wed, Feb 18, 2009 at 2:57 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

The point I'm trying to make is that we should deliver IEEE-compliant
results if we are on a platform that complies with the spec. Right down
to the minus sign. If that surprises people who are unfamiliar with the
spec, well, there are a lot of things about floating point arithmetic
that surprise people who aren't familiar with it.

Agreed. There are plenty of things about floats that are downright
wonky, and when people start seeing minus zero in their float
computations it might prompt them into doing some reading, and
figuring out that what they really wanted was numeric.

I pulled the special code out of float8um/float4um and got the following
two changes in the regression tests:

*** src/test/regress/expected/numerology.out	Mon Aug  4 22:43:18 2008
--- src/test/regress/results/numerology.out	Tue Feb 17 20:05:01 2009
***************
*** 92,98 ****
    ORDER BY two, max_float, min_float;
   two |      max_float       |       min_float       
  -----+----------------------+-----------------------
!    1 | 1.2345678901234e+200 |                     0
     2 |                    0 | -1.2345678901234e+200
  (2 rows)
--- 92,98 ----
    ORDER BY two, max_float, min_float;
   two |      max_float       |       min_float       
  -----+----------------------+-----------------------
!    1 | 1.2345678901234e+200 |                    -0
     2 |                    0 | -1.2345678901234e+200
  (2 rows)

***************
*** 104,110 ****
ORDER BY two, max_float, min_float;
two | max_float | min_float
-----+----------------------+-----------------------
! 1 | 1.2345678901234e+200 | 0
2 | 0 | -1.2345678901234e+200
(2 rows)

--- 104,110 ----
    ORDER BY two, max_float, min_float;
   two |      max_float       |       min_float       
  -----+----------------------+-----------------------
!    1 | 1.2345678901234e+200 |                    -0
     2 |                    0 | -1.2345678901234e+200
  (2 rows)

======================================================================

This is on a minus-zero-clean platform of course (same results on Fedora
9 and current Mac OS X). My HP box still produces the old results,
so we will need two variants of this expected-result file. Other
platforms might show yet other diffs of course, but we'll have to wait
for buildfarm results to know more.

Last call for objections ...

regards, tom lane