[php-src] Issue #12153: Processing of round() function is incorrect

From: Date: Fri, 08 Sep 2023 12:47:51 +0000
Subject: [php-src] Issue #12153: Processing of round() function is incorrect
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-245362@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/12153 Author: SakiTakamachi ### Description The following code: ```php <?php var_dump(round(1.4999999999999998, 0, PHP_ROUND_HALF_UP)); ``` Debugging with GDB: ``` Breakpoint 1, _php_math_round (value=1.4999999999999998, places=0, mode=1) at /var/www/html/php-src/ext/standard/math.c:126 126 PHPAPI double _php_math_round(double value, int places, int mode) { (gdb) n 131 if (!zend_finite(value) || value == 0.0) { (gdb) 135 places = places < INT_MIN+1 ? INT_MIN+1 : places; (gdb) 136 precision_places = 14 - php_intlog10abs(value); (gdb) 138 f1 = php_intpow10(abs(places)); (gdb) 143 if (precision_places > places && precision_places - 15 < places) { (gdb) 144 int64_t use_precision = precision_places < INT_MIN+1 ? INT_MIN+1 : precision_places; (gdb) 146 f2 = php_intpow10(abs((int)use_precision)); (gdb) 147 if (use_precision >= 0) { (gdb) 148 tmp_value = value * f2; (gdb) s 154 tmp_value = php_round_helper(tmp_value, mode); (gdb) php_round_helper (value=149999999999999.97, mode=1) at /var/www/html/php-src/ext/standard/math.c:99 99 if (value >= 0.0) { (gdb) n 100 tmp_value = floor(value + 0.5); (gdb) 101 if ((mode == PHP_ROUND_HALF_DOWN && value == (-0.5 + tmp_value)) || (gdb) 117 return tmp_value; (gdb) 118 } (gdb) _php_math_round (value=1.4999999999999998, places=0, mode=1) at /var/www/html/php-src/ext/standard/math.c:156 156 use_precision = places - precision_places; (gdb) 157 use_precision = use_precision < INT_MIN+1 ? INT_MIN+1 : use_precision; (gdb) 159 f2 = php_intpow10(abs((int)use_precision)); (gdb) 161 tmp_value = tmp_value / f2; (gdb) 143 if (precision_places > places && precision_places - 15 < places) { (gdb) 176 tmp_value = php_round_helper(tmp_value, mode); (gdb) 179 if (abs(places) < 23) { (gdb) 180 if (places > 0) { (gdb) 183 tmp_value = tmp_value * f1; (gdb) 180 if (places > 0) { (gdb) 204 return tmp_value; (gdb) 205 } ``` php_round_helper adds 0.5, but isn't this process completely meaningless? It appears that the decimal point position of the actual value is significantly different from the expected value. Regards. ### PHP Version PHP 8.1(build branch) ### Operating System Ubuntu22.04 (docker image)

« previous php.bugs (#245362) next »