Richard Wang wrote: > I expected 0 ^ 123.3 to be 0, but it reported error as follows > > postgres=# select 0 ^ 123.3; > ERROR: cannot take logarithm of zero > > I find that there is a bug in numeric_power() function > the function caculates a ^ b based on the algorithm e ^ (lna * b) > as you see, ln0 is not valid
I have developed the attached patch which fixes 0 ^ 123.3. It also fixes the case for 0 ^ 0.0 so it returns 1 instead of an error --- see the C comment for why one is the proper return value. float pow() already returned one in this case: test=> select 0 ^ 0; ?column? ---------- 1 (1 row) test=> select 0 ^ 0.0; ?column? ---------- 1 (1 row) test=> select 0 ^ 3.4; ?column? ---------- 1 (1 row) -- Bruce Momjian <[EMAIL PROTECTED]> http://momjian.us EnterpriseDB http://enterprisedb.com + If your life is a hard drive, Christ can be your backup. +
Index: src/backend/utils/adt/numeric.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v retrieving revision 1.110 diff -c -c -r1.110 numeric.c *** src/backend/utils/adt/numeric.c 21 Apr 2008 00:26:45 -0000 1.110 --- src/backend/utils/adt/numeric.c 7 May 2008 20:05:01 -0000 *************** *** 5170,5175 **** --- 5170,5187 ---- int local_rscale; double val; + /* + * This avoids log(0) for cases of 0 raised to a non-integer. + * We also treat 0 ^ 0 == 1 because it is the best value for discrete + * mathematics, and most programming languages do this. + * http://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power + */ + if (cmp_var(base, &const_zero) == 0) + { + set_var_from_var(&const_one, result); + return; + } + /* If exp can be represented as an integer, use power_var_int */ if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1) { *************** *** 5266,5280 **** NumericVar base_prod; int local_rscale; - /* Detect some special cases, particularly 0^0. */ - switch (exp) { case 0: - if (base->ndigits == 0) - ereport(ERROR, - (errcode(ERRCODE_FLOATING_POINT_EXCEPTION), - errmsg("zero raised to zero is undefined"))); set_var_from_var(&const_one, result); result->dscale = rscale; /* no need to round */ return; --- 5278,5286 ----
-- Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-patches