pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Tom Lane <tgl@sss.pgh.pa.us>
To: pgsql-hackers@lists.postgresql.org
Cc: Dean Rasheed <dean.a.rasheed@gmail.com>
Cc: Andres Freund <andres@anarazel.de>
Subject: NaN divided by zero should yield NaN
Date: Thu, 16 Jul 2020 15:29:45 -0400
Message-ID: <3421746.1594927785@sss.pgh.pa.us> (raw)

Dean Rasheed questioned this longstanding behavior:

regression=# SELECT 'nan'::float8 / '0'::float8;
ERROR:  division by zero

After a bit of research I think he's right: per IEEE 754 this should
yield NaN, not an error.  Accordingly I propose the attached patch.
This is probably not something to back-patch, though.

One thing that's not very clear to me is which of these spellings
is preferable:

	if (unlikely(val2 == 0.0) && !isnan(val1))
	if (unlikely(val2 == 0.0 && !isnan(val1)))

I think we can reject this variant:

	if (unlikely(val2 == 0.0) && unlikely(!isnan(val1)))

since actually the second condition *is* pretty likely.
But I don't know which of the first two would give better
code.  Andres, any thoughts?

			regards, tom lane

Attachments:

nan-over-zero-is-nan.patch (text/x-diff, 3.0K) download diff --git a/src/include/utils/float.h b/src/include/utils/float.h index 8d4bbc51a6..e2aae8ef17 100644 --- a/src/include/utils/float.h +++ b/src/include/utils/float.h @@ -222,7 +222,7 @@ float4_div(const float4 val1, const float4 val2) { float4 result; - if (unlikely(val2 == 0.0f)) + if (unlikely(val2 == 0.0f) && !isnan(val1)) float_zero_divide_error(); result = val1 / val2; if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2)) @@ -238,7 +238,7 @@ float8_div(const float8 val1, const float8 val2) { float8 result; - if (unlikely(val2 == 0.0)) + if (unlikely(val2 == 0.0) && !isnan(val1)) float_zero_divide_error(); result = val1 / val2; if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2)) diff --git a/src/test/regress/expected/float4-misrounded-input.out b/src/test/regress/expected/float4-misrounded-input.out index 6c89af6394..38b847a1ad 100644 --- a/src/test/regress/expected/float4-misrounded-input.out +++ b/src/test/regress/expected/float4-misrounded-input.out @@ -143,6 +143,12 @@ SELECT 'nan'::float4 / 'nan'::float4; NaN (1 row) +SELECT 'nan'::float4 / '0'::float4; + ?column? +---------- + NaN +(1 row) + SELECT 'nan'::numeric::float4; float4 -------- diff --git a/src/test/regress/expected/float4.out b/src/test/regress/expected/float4.out index d6c22c1752..310402b6ee 100644 --- a/src/test/regress/expected/float4.out +++ b/src/test/regress/expected/float4.out @@ -143,6 +143,12 @@ SELECT 'nan'::float4 / 'nan'::float4; NaN (1 row) +SELECT 'nan'::float4 / '0'::float4; + ?column? +---------- + NaN +(1 row) + SELECT 'nan'::numeric::float4; float4 -------- diff --git a/src/test/regress/expected/float8.out b/src/test/regress/expected/float8.out index c635dd7dcb..2304b579d2 100644 --- a/src/test/regress/expected/float8.out +++ b/src/test/regress/expected/float8.out @@ -126,6 +126,12 @@ SELECT 'nan'::float8 / 'nan'::float8; NaN (1 row) +SELECT 'nan'::float8 / '0'::float8; + ?column? +---------- + NaN +(1 row) + SELECT 'nan'::numeric::float8; float8 -------- diff --git a/src/test/regress/sql/float4.sql b/src/test/regress/sql/float4.sql index 393d98fb14..1fcf823c21 100644 --- a/src/test/regress/sql/float4.sql +++ b/src/test/regress/sql/float4.sql @@ -50,6 +50,7 @@ SELECT ' INFINITY x'::float4; SELECT 'Infinity'::float4 + 100.0; SELECT 'Infinity'::float4 / 'Infinity'::float4; SELECT 'nan'::float4 / 'nan'::float4; +SELECT 'nan'::float4 / '0'::float4; SELECT 'nan'::numeric::float4; SELECT '' AS five, * FROM FLOAT4_TBL; diff --git a/src/test/regress/sql/float8.sql b/src/test/regress/sql/float8.sql index 288969aed6..f103871cdb 100644 --- a/src/test/regress/sql/float8.sql +++ b/src/test/regress/sql/float8.sql @@ -43,6 +43,7 @@ SELECT ' INFINITY x'::float8; SELECT 'Infinity'::float8 + 100.0; SELECT 'Infinity'::float8 / 'Infinity'::float8; SELECT 'nan'::float8 / 'nan'::float8; +SELECT 'nan'::float8 / '0'::float8; SELECT 'nan'::numeric::float8; SELECT '' AS five, * FROM FLOAT8_TBL;

view thread (3+ messages)  latest in thread

Message-ID: <3421746.1594927785@sss.pgh.pa.us>
Permalink:  ../3421746.1594927785@sss.pgh.pa.us/
Also on:    postgresql.org/message-id/3421746.1594927785@sss.pgh.pa.us

 ·  · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-hackers@postgresql.org
  Cc: tgl@sss.pgh.pa.us, pgsql-hackers@lists.postgresql.org, dean.a.rasheed@gmail.com, andres@anarazel.de
  Subject: Re: NaN divided by zero should yield NaN
  In-Reply-To: <3421746.1594927785@sss.pgh.pa.us>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox