]> granicus.if.org Git - php/commitdiff
@- Improved round() to allow specification of rounding precision.
authorAndrei Zmievski <andrei@php.net>
Wed, 17 May 2000 12:50:04 +0000 (12:50 +0000)
committerAndrei Zmievski <andrei@php.net>
Wed, 17 May 2000 12:50:04 +0000 (12:50 +0000)
@  (Andrei, Todd Kirby <kirbyt@yahoo.com>)

configure.in
ext/standard/math.c

index 9d8e76ba2b93153692d5b297eb2257391cef80ed..be04a2c87ab63c9591ce19b431feda0aa54721ea 100644 (file)
@@ -346,7 +346,6 @@ putenv \
 random \
 rand_r \
 regcomp \
-rint \
 setitimer \
 setlocale \
 setsockopt \
index 3d15905823d0d7f2f92e6be55854f0fd566f91d3..5671c9426a8f4bb25897f1663e131e091d6feab3 100644 (file)
@@ -101,45 +101,59 @@ PHP_FUNCTION(floor) {
 }
 
 /* }}} */
-/* {{{ proto int round(double number)
-   Returns the rounded value of the number */
 
-#ifndef HAVE_RINT
-/* emulate rint */
-inline double rint(double n)
-{
-       double i, f;
-       f = modf(n, &i);
-       if (f > .5)
-               i++;
-       else if (f < -.5)
-               i--;
-       return i;
-}
-#endif
 
+/* {{{ proto int round(double number, int precision)
+   Returns the number rounded to specified precision. */
 PHP_FUNCTION(round)
 {
-       zval **value;
-
-       if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &value) == FAILURE) {
+       zval **value, **precision;
+       int places = 0;
+       double f, return_val;
+       
+       if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 ||
+               zend_get_parameters_ex(ZEND_NUM_ARGS(), &value, &precision) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
 
+       if (ZEND_NUM_ARGS() == 2) {
+               convert_to_long_ex(precision);
+               places = (int) Z_LVAL_PP(precision);
+       }
+
        convert_scalar_to_number_ex(value);
 
-       if ((*value)->type == IS_DOUBLE) {
-               double d;
-               d=rint((*value)->value.dval);
-               if(d==0.0) d=0.0; /* workaround for rint() returning -0 instead of 0 */
-               RETURN_DOUBLE(d);
-       } else if ((*value)->type == IS_LONG) {
-               RETURN_DOUBLE((double)(*value)->value.lval);
+       switch (Z_TYPE_PP(value)) {
+               case IS_LONG:
+                       /* Simple case - long that doesn't need to be rounded. */
+                       if (places >= 0) {
+                               RETURN_DOUBLE((double) Z_LVAL_PP(value));
+                       }
+                       /* break omitted intentionally */
+
+               case IS_DOUBLE:
+                       return_val = (Z_TYPE_PP(value) == IS_LONG) ? Z_LVAL_PP(value) : Z_DVAL_PP(value);
+
+                       f = pow(10.0, places);
+
+                       return_val *= f;
+                       if (return_val >= 0.0)
+                               return_val = floor(return_val + 0.5);
+                       else
+                               return_val = ceil(return_val - 0.5);
+                       return_val /= f;
+
+                       RETURN_DOUBLE(return_val);
+                       break;
+
+               default:
+                       RETURN_FALSE;
+                       break;
        }
-       RETURN_FALSE;
 }
-
 /* }}} */
+
+
 /* {{{ proto double sin(double number)
    Returns the sine of the number in radians */