w3schools round redondear half hacia funciona even como cantidad arriba php rounding floor bcmath ceil

round - redondear cantidad php



¿Cómo ceil, piso y números redondos? (4)

Necesito imitar la funcionalidad exacta de las funciones ceil() , floor() y round() en los números bcmath . Ya encontré una pregunta muy similar, pero desafortunadamente la respuesta proporcionada no es lo suficientemente buena para mí, ya que carece de soporte. para los números negativos y el argumento de precisión para la función round () falta .

Me preguntaba si alguien puede encontrar una solución bastante corta y elegante para este problema.

Todas las aportaciones son apreciadas, gracias!


Aquí hay algunos que admiten números negativos y argumentos de precisión para el redondeo.

function bcceil($val) { if (($pos = strpos($val, ''.'')) !== false) { if ($val[$pos+1] != 0 && $val[0] != ''-'') return bcadd(substr($val, 0, $pos), 1, 0); else return substr($val, 0, $pos); } return $val; } function bcfloor($val) { if (($pos = strpos($val, ''.'')) !== false) { if ($val[$pos+1] != 0 && $val[0] == ''-'') return bcsub(substr($val, 0, $pos), 1, 0); else return substr($val, 0, $pos); } return $val; } function bcround($val, $precision = 0) { if (($pos = strpos($val, ''.'')) !== false) { if ($precision > 0) { $int = substr($val, 0, $pos); $pos2 = ++$pos+$precision; if ($pos2 < strlen($val)) { $val2 = sprintf(''%s.%s'', substr($val, $pos, $pos2-$pos), substr($val, $pos2)); $val2 = $val2[0] >= 5 ? bcceil($val2) : bcfloor($val2); if (strlen($val2) > $precision) return bcadd($int, $val[0] == ''-'' ? -1 : 1, 0); else return sprintf(''%s.%s'', $int, rtrim($val2, ''0'')); } return $val; } else { if ($val[$pos+1] >= 5) return ($val[0] == ''-'' ? bcfloor($val) : bcceil($val)); else return ($val[0] == ''-'' ? bcceil($val) : bcfloor($val)); } } return $val; }


Después de una noche perdida tratando de resolver este problema, creo que he encontrado una solución bastante simple, aquí está:

function bcceil($number) { if (strpos($number, ''.'') !== false) { if (preg_match("~/.[0]+$~", $number)) return bcround($number, 0); if ($number[0] != ''-'') return bcadd($number, 1, 0); return bcsub($number, 0, 0); } return $number; } function bcfloor($number) { if (strpos($number, ''.'') !== false) { if (preg_match("~/.[0]+$~", $number)) return bcround($number, 0); if ($number[0] != ''-'') return bcadd($number, 0, 0); return bcsub($number, 1, 0); } return $number; } function bcround($number, $precision = 0) { if (strpos($number, ''.'') !== false) { if ($number[0] != ''-'') return bcadd($number, ''0.'' . str_repeat(''0'', $precision) . ''5'', $precision); return bcsub($number, ''0.'' . str_repeat(''0'', $precision) . ''5'', $precision); } return $number; }

Creo que no me perdí nada, si alguien puede detectar algún error, por favor, hágamelo saber. Aquí hay algunas pruebas:

assert(bcceil(''4'') == ceil(''4'')); // true assert(bcceil(''4.3'') == ceil(''4.3'')); // true assert(bcceil(''9.999'') == ceil(''9.999'')); // true assert(bcceil(''-3.14'') == ceil(''-3.14'')); // true assert(bcfloor(''4'') == floor(''4'')); // true assert(bcfloor(''4.3'') == floor(''4.3'')); // true assert(bcfloor(''9.999'') == floor(''9.999'')); // true assert(bcfloor(''-3.14'') == floor(''-3.14'')); // true assert(bcround(''3'', 0) == number_format(''3'', 0)); // true assert(bcround(''3.4'', 0) == number_format(''3.4'', 0)); // true assert(bcround(''3.5'', 0) == number_format(''3.5'', 0)); // true assert(bcround(''3.6'', 0) == number_format(''3.6'', 0)); // true assert(bcround(''1.95583'', 2) == number_format(''1.95583'', 2)); // true assert(bcround(''5.045'', 2) == number_format(''5.045'', 2)); // true assert(bcround(''5.055'', 2) == number_format(''5.055'', 2)); // true assert(bcround(''9.999'', 2) == number_format(''9.999'', 2)); // true


function bcnegative($n) { return strpos($n, ''-'') === 0; // Is the number less than 0? } function bcceil($n) { return bcnegative($n) ? ''-'' . bcfloor(substr($n, 1)) : bcadd(strtok($n, ''.''), strtok(''.'') != 0); } function bcfloor($n) { return bcnegative($n) ? ''-'' . bcceil(substr($n, 1)) : strtok($n, ''.''); } function bcround($n, $p = 0) { $e = bcpow(10, $p + 1); return bcdiv(bcadd(bcmul($n, $e, 0), bcnegative($n) ? -5 : 5), $e, $p); }


function getBcRound($number, $precision = 0) { $precision = ($precision < 0) ? 0 : (int) $precision; if (strcmp(bcadd($number, ''0'', $precision), bcadd($number, ''0'', $precision+1)) == 0) { return bcadd($number, ''0'', $precision); } if (getBcPresion($number) - $precision > 1) { $number = getBcRound($number, $precision + 1); } $t = ''0.'' . str_repeat(''0'', $precision) . ''5''; return $number < 0 ? bcsub($number, $t, $precision) : bcadd($number, $t, $precision); } function getBcPresion($number) { $dotPosition = strpos($number, ''.''); if ($dotPosition === false) { return 0; } return strlen($number) - strpos($number, ''.'') - 1; } var_dump(getBcRound(''3'', 0) == number_format(''3'', 0)); var_dump(getBcRound(''3.4'', 0) == number_format(''3.4'', 0)); var_dump(getBcRound(''3.56'', 0) == number_format(''3.6'', 0)); var_dump(getBcRound(''1.95583'', 2) == number_format(''1.95583'', 2)); var_dump(getBcRound(''5.045'', 2) == number_format(''5.045'', 2)); var_dump(getBcRound(''5.055'', 2) == number_format(''5.055'', 2)); var_dump(getBcRound(''9.999'', 2) == number_format(''9.999'', 2)); var_dump(getBcRound(''5.0445'', 5) == number_format(''5.044500'', 5)); var_dump(getBcRound(''5.0445'', 4) == number_format(''5.04450'', 4)); var_dump(getBcRound(''5.0445'', 3) == number_format(''5.0445'', 3)); var_dump(getBcRound(''5.0445'', 2) == number_format(''5.045'', 2)); var_dump(getBcRound(''5.0445'', 1) == number_format(''5.05'', 1)); var_dump(getBcRound(''5.0445'', 0) == number_format(''5.0'', 0));// var_dump(getBcRound(''5.04455'', 2) == number_format(''5.045'', 2)); var_dump(getBcRound(''99.999'', 2) == number_format(''100.000'', 2)); var_dump(getBcRound(''99.999'') == number_format(''99.999'', 0)); var_dump(getBcRound(''99.999'', ''a'') == number_format(''99.999'', 0)); var_dump(getBcRound(''99.999'', -1.5) == number_format(''99.999'', 0)); var_dump(getBcRound(''-0.00001'', 2) == number_format(''-0.000'', 2)); var_dump(getBcRound(''-0.0000'', 2) == number_format(''0'', 2)); var_dump(getBcRound(''-4.44455'', 2) == number_format(''-4.445'', 2)); var_dump(getBcRound(''-4.44555'', 0) == number_format(''-4.5'', 0)); var_dump(getBcRound(''-4.444444444444444444444444444444444444444444445'', 0) == number_format(''-4.5'', 0));