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

Reply via email to