[php-src] Issue #12153: Processing of round() function is incorrect
| From: | SakiTakamachi | 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)