mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
ext/bcmath: If the result is 0, n_scale is set to 0. (#18056)
This commit is contained in:
1
NEWS
1
NEWS
@@ -4,6 +4,7 @@ PHP NEWS
|
||||
|
||||
- BCMath:
|
||||
. Simplify `bc_divide()` code. (SakiTakamachi)
|
||||
. If the result is 0, n_scale is set to 0. (SakiTakamachi)
|
||||
|
||||
- CLI:
|
||||
. Add --ini=diff to print INI settings changed from the builtin default.
|
||||
|
||||
@@ -807,8 +807,8 @@ PHP_FUNCTION(bcround)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
bc_round(num, precision, mode, &result);
|
||||
RETVAL_NEW_STR(bc_num2str_ex(result, result->n_scale));
|
||||
size_t scale = bc_round(num, precision, mode, &result);
|
||||
RETVAL_NEW_STR(bc_num2str_ex(result, scale));
|
||||
|
||||
cleanup: {
|
||||
bc_free_num(&num);
|
||||
@@ -1799,9 +1799,10 @@ PHP_METHOD(BcMath_Number, round)
|
||||
bcmath_number_obj_t *intern = get_bcmath_number_from_zval(ZEND_THIS);
|
||||
|
||||
bc_num ret = NULL;
|
||||
bc_round(intern->num, precision, rounding_mode, &ret);
|
||||
size_t scale = bc_round(intern->num, precision, rounding_mode, &ret);
|
||||
bc_rm_trailing_zeros(ret);
|
||||
|
||||
bcmath_number_obj_t *new_intern = bcmath_number_new_obj(ret, ret->n_scale);
|
||||
bcmath_number_obj_t *new_intern = bcmath_number_new_obj(ret, scale);
|
||||
RETURN_OBJ(&new_intern->std);
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ bool bc_divmod(bc_num num1, bc_num num2, bc_num *quo, bc_num *rem, size_t scale)
|
||||
|
||||
bc_num bc_floor_or_ceil(bc_num num, bool is_floor);
|
||||
|
||||
void bc_round(bc_num num, zend_long places, zend_long mode, bc_num *result);
|
||||
size_t bc_round(bc_num num, zend_long places, zend_long mode, bc_num *result);
|
||||
|
||||
typedef enum {
|
||||
OK,
|
||||
|
||||
@@ -430,6 +430,7 @@ bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale)
|
||||
_bc_rm_leading_zeros(*quot);
|
||||
if (bc_is_zero(*quot)) {
|
||||
(*quot)->n_sign = PLUS;
|
||||
(*quot)->n_scale = 0;
|
||||
} else {
|
||||
(*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS;
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ bool bc_divmod(bc_num num1, bc_num num2, bc_num *quot, bc_num *rem, size_t scale
|
||||
(*rem)->n_scale = MIN(scale, (*rem)->n_scale);
|
||||
if (bc_is_zero(*rem)) {
|
||||
(*rem)->n_sign = PLUS;
|
||||
(*rem)->n_scale = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -264,6 +264,7 @@ bc_num bc_multiply(bc_num n1, bc_num n2, size_t scale)
|
||||
_bc_rm_leading_zeros(prod);
|
||||
if (bc_is_zero(prod)) {
|
||||
prod->n_sign = PLUS;
|
||||
prod->n_scale = 0;
|
||||
}
|
||||
return prod;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
#include "private.h"
|
||||
#include <stddef.h>
|
||||
|
||||
void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
|
||||
/* Returns the scale of the value after rounding. */
|
||||
size_t bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
|
||||
{
|
||||
/* clear result */
|
||||
bc_free_num(result);
|
||||
@@ -43,19 +44,19 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
|
||||
case PHP_ROUND_HALF_ODD:
|
||||
case PHP_ROUND_TOWARD_ZERO:
|
||||
*result = bc_copy_num(BCG(_zero_));
|
||||
return;
|
||||
return 0;
|
||||
|
||||
case PHP_ROUND_CEILING:
|
||||
if (num->n_sign == MINUS) {
|
||||
*result = bc_copy_num(BCG(_zero_));
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case PHP_ROUND_FLOOR:
|
||||
if (num->n_sign == PLUS) {
|
||||
*result = bc_copy_num(BCG(_zero_));
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -67,7 +68,7 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
|
||||
|
||||
if (bc_is_zero(num)) {
|
||||
*result = bc_copy_num(BCG(_zero_));
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If precision is -3, it becomes 1000. */
|
||||
@@ -78,7 +79,7 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
|
||||
}
|
||||
(*result)->n_value[0] = 1;
|
||||
(*result)->n_sign = num->n_sign;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Just like bcadd('1', '1', 4) becomes '2.0000', it pads with zeros at the end if necessary. */
|
||||
@@ -90,7 +91,7 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
|
||||
(*result)->n_sign = num->n_sign;
|
||||
memcpy((*result)->n_value, num->n_value, num->n_len + num->n_scale);
|
||||
}
|
||||
return;
|
||||
return precision;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -222,7 +223,12 @@ up:
|
||||
}
|
||||
|
||||
check_zero:
|
||||
if (bc_is_zero(*result)) {
|
||||
(*result)->n_sign = PLUS;
|
||||
{
|
||||
size_t scale = (*result)->n_scale;
|
||||
if (bc_is_zero(*result)) {
|
||||
(*result)->n_sign = PLUS;
|
||||
(*result)->n_scale = 0;
|
||||
}
|
||||
return scale;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user