1
0
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:
Saki Takamachi
2025-03-14 17:52:50 +09:00
committed by GitHub
parent fa1effdb3c
commit 32547f1127
7 changed files with 25 additions and 14 deletions

1
NEWS
View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}
}