note 110823 deleted from function.fmod by danbrown

From: Date: Wed, 12 Dec 2012 16:12:22 +0000
Subject: note 110823 deleted from function.fmod by danbrown
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-192496@lists.php.net to get a copy of this message
Note Submitter: verdy_p at wanadoo dot fr ---- Square root of 0 is perfectly defined. 0 elevated at any non-zero finite power is always 0, even when you work with complexes. The ONLY power of 0 whose result is NaN is 0^0 : 0^(1/2) = exp(log(0)*(1/2)) = exp(-INF*(1/2)) = exp(-INF) = 0 0^0 = exp(log(0)*0) = exp(-INF*0) = exp(NaN) = NaN 1^0 = exp(log(1)*0) = exp(0*0) = exp(0) = 1 (-2)^0 is more difficult to define, but it remains valid: function pow(double a, double b) { if (b == floor(b)) { if ((b/2)=floor(b/2)) // b is even return exp(log(abs(a))*b); else // b is odd return exp(log(abs(a))*b)*sng(a); } else { // If b is the inverse of an integer, the result has // multiple solutions, not real but complex. // We could take an arbitrary complex root such as // such as the root with the smallest positive imaginary // part and the largest real part (possibly negative). // But if the function must return only a real value, // there's no solution. // If b any other non-integer value, there's no real or // complex solution at all: // Note that only inverses of powers of 2 are exactly // stored (e.g. b==1.2, but not b==1/3; this limits // our detection of cubic roots here). throw FPexception; } } With this function (-2)^0 = pow(-2,0), a==-2 and b==0 is an even integer, so we return: exp(log(abs(a))*b) = exp(log(abs(-2))*0) = exp(log(2)*0) =exp(0) = 1 The case where this cannot return a value is when a==0 and b==0 (even integer): exp(log(abs(a))*b) = exp(log(abs(0))*0) = exp(log(0)*0) =exp(-INF*0) = exp(NaN) = NaN For other cases of a^0, where a != 0, we have: exp(log(abs(a))*b) = exp(log(abs(a))*0) = exp(FINITE*0) =exp(0) = 1 If a is infinite (positive or negative) and b positive, we have: exp(log(abs(a))*b) = exp(log(abs(INF))*b) = exp(+INF*+FINITE) =exp(+INF) = +INF If a is infinite (positive or negative) and b negative, we have: exp(log(abs(a))*b) = exp(log(abs(INF))*b) = exp(+INF*-FINITE) =exp(-INF) = 0 If a is NaN, we have: exp(log(abs(a))*b) = exp(log(abs(NaN))*b) = exp(NaN*b) =exp(NaN) = NaN The pow(a,b) function in PHP should then be defined for negative values of a, and for all finite integer values of b if a is positive. In order to define a return value when b is a negative power of 2, this works only up to the precision of doubles : each ime b is divided by 2 you loose 1 bit of precision in the logarithm of a, and the result of the multiplication also becomes twice less significant. If doubles cannot store powers of 2 lower than 2^-1024, then the result of a^b will be NaN if b < 2^-104.

« previous php.notes (#192496) next »