Подтвердить что ты не робот

PHP Как округлить до двух знаков после запятой?

Мне нужно округлить десятичное число в PHP до двух знаков после запятой, чтобы:

49.955

становится...

49.95

Я пробовал number_format, но это просто округляет значение до 49.96. Я не могу использовать substr, потому что число может быть меньше (например, 7.950). Мне пока не удалось найти ответ.

Любая помощь очень ценится.

4b9b3361

Ответ 1

Это может работать: floor($number * 100) / 100

Ответ 2

Вот хорошая функция, которая делает трюк без использования строковых функций:

<?php
function floorp($val, $precision)
{
    $mult = pow(10, $precision); // Can be cached in lookup table        
    return floor($val * $mult) / $mult;
}

print floorp(49.955, 2);
?>

Другой вариант - вычесть дробь перед округлением:

function floorp($val, $precision)
{
    $half = 0.5 / pow(10, $precision); // Can be cached in a lookup table
    return round($val - $half, $precision);
}

Ответ 3

К сожалению, ни один из предыдущих ответов (включая принятый) не работает для всех возможных входных данных.

1) sprintf('%1.'.$precision.'f', $val)

Сбой с точностью 2: 14.239 должен вернуть 14.23 (но в этом случае возвращает 14.24).

2) floatval(substr($val, 0, strpos($val, '.') + $precision + 1))

Сбой с точностью 0: 14 должен вернуть 14 (но в этом случае возвращает 1)

3) substr($val, 0, strrpos($val, '.', 0) + (1 + $precision))

Сбой с точностью 0: -1 должен вернуть -1 (но в этом случае возвращает '-')

4) floor($val * pow(10, $precision)) / pow(10, $precision)

Хотя я использовал это широко, недавно я обнаружил недостаток в этом; это не подходит для некоторых значений тоже. С точностью до 2: 2,05 должен возвращать 2,05 (но в этом случае возвращает 2,04 !!)

Пока что единственный способ пройти все мои тесты - это, к сожалению, использовать манипуляции со строками. Мое решение на основе рационального босса:

function floorDec($val, $precision = 2) {
    if ($precision < 0) { $precision = 0; }
    $numPointPosition = intval(strpos($val, '.'));
    if ($numPointPosition === 0) { //$val is an integer
        return $val;
    }
    return floatval(substr($val, 0, $numPointPosition + $precision + 1));
}

Эта функция работает с положительными и отрицательными числами, а также с любой необходимой точностью.

Ответ 4

Умножьте свой ввод на 100, floor(), затем разделите результат на 100.

Ответ 5

Попробуйте round() функция

Пример: round($num, 2, PHP_ROUND_HALF_DOWN);

Ответ 6

function roundDown($decimal, $precision)
{
    $sign = $decimal > 0 ? 1 : -1;
    $base = pow(10, $precision);
    return floor(abs($decimal) * $base) / $base * $sign;
}

// Examples
roundDown(49.955, 2);           // output: 49.95
roundDown(-3.14159, 4);         // output: -3.1415
roundDown(1000.000000019, 8);   // output: 1000.00000001

Эта функция работает с положительными и отрицательными десятичными знаками с любой точностью.

Пример кода здесь: http://codepad.org/1jzXjE5L

Ответ 7

function floorToPrecision($val, $precision = 2) {
        return floor(round($val * pow(10, $precision), $precision)) / pow(10, $precision);
    }

Ответ 8

Я думаю, что есть довольно простой способ добиться этого:

$rounded = bcdiv($val, 1, $precision);

Вот рабочий пример. Вам нужно установить BCMath, но я думаю, что он обычно связан с установкой PHP. :) Вот документация.

Ответ 9

Вы можете использовать PHP-функцию bcdiv.

bcdiv(49.955, 1, 2)

Ответ 10

Использовать форматированный вывод

sprintf("%1.2f",49.955) //49.95

DEMO

Ответ 11

Вы можете использовать:

$num = 49.9555;
echo substr($num, 0, strpos($num, '.') + 3);

Ответ 12

Альтернативное решение с использованием регулярного выражения, которое должно работать для всех положительных или отрицательных чисел, целых или десятичных знаков:

if (preg_match('/^-?(\d+\.?\d{1,2})\d*$/', $originalValue, $matches)){
    $roundedValue = $matches[1];
} else {
    throw new \Exception('Cannot round down properly '.$originalValue.' to two decimal places');
}

Ответ 13

Если вы хотите округлить десятичную дробь вниз только тогда, когда последняя ее часть равна 5 или ниже, тогда лучшим решением будет использование:

round(4.955,2,PHP_ROUND_HALF_DOWN);

Теперь, если вы хотите всегда округлять десятичные дроби вниз и по-прежнему контролировать количество десятичных дробей, лучшее решение:

round(floor(4.957*100)/100,2)

Также учтите, что число "100" должно масштабироваться вместе с десятичным знаком "2". Например, если вы хотите 4 десятичных знака, вам придется умножить на 10000 и разделить на 10000, чтобы вы потеряли только числа после этой точки.

Ответ 14

Основываясь на ответах @huysentruitw и @Alex, я придумал следующую функцию, которая должна помочь.

Он проходит все тесты, приведенные в ответе Алекса (а почему это невозможно), и основывается на ответе huysentruitw.

function trim_number($number, $decimalPlaces) {
    $delta = (0 <=> $number) * (0.5 / pow(10, $decimalPlaces));
    $result = round($number + $delta, $decimalPlaces);
    return $result ?: 0; // get rid of negative zero
}

Ключ заключается в том, чтобы добавить или вычесть дельту на основе исходного числового знака, чтобы поддерживать обрезку также отрицательных чисел. Последнее, что нужно сделать, это избавиться от отрицательных нулей (-0), так как это может быть нежелательным поведением.

Ссылка на "тестовую" площадку.

ОБНОВЛЕНИЕ: bcdiv, кажется, путь.

// round afterwards to cast 0.00 to 0
// set $divider to 1 when no division is required
round(bcdiv($number, $divider, $decimalPlaces), $decimalPlaces);

Ответ 15

sprintf("%1.2f",49.955) //49.95

если вам нужно обрезать десятичные знаки без округления - это не подходит, потому что оно будет работать корректно до 49.95 5 в конце, если число больше, например, 49.95 7 он будет округлен до 49,96

Мне кажется, что ответ Lght с полом является самым универсальным.

Ответ 17

Вы попробовали round($val,2)?

Подробнее о round() функция