Я хочу сбросить десятичные знаки без округления. Например, если у меня есть 1.505, я хочу отбросить последнее десятичное число, а значение должно быть 1.50. Есть ли такая функция в PHP?
Отбрасывание десятичных знаков PHP без округления
Ответ 1
Вам нужно floor() следующим образом:
$rounded = floor($float*100)/100;
Или вы отбрасываете целое число:
$rounded = 0.01 * (int)($float*100);
Таким образом, он не будет округлять.
Ответ 2
$float = 1.505;
echo sprintf("%.2f", $float);
//outputs 1.50
Ответ 3
Может быть, это слишком поздно, но здесь хороший подход:
$getTruncatedValue = function( $value, $precision )
{
//Casts provided value
$value = ( string )$value;
//Gets pattern matches
preg_match( "/(-+)?\d+(\.\d{1,".$precision."})?/" , $value, $matches );
//Returns the full pattern match
return $matches[0];
};
var_dump
(
$getTruncatedValue(1.123,1), //string(3) "1.1"
$getTruncatedValue(1.345,2), //string(4) "1.34"
$getTruncatedValue(1.678,3), //string(5) "1.678"
$getTruncatedValue(1.90123,4) //string(6) "1.9012"
);
- Единственной ошибкой в этом подходе может быть необходимость использования регулярного выражения (которое иногда может привести к снижению производительности).
Примечание. Очень сложно найти собственный подход к усечению десятичных знаков, и я думаю, что это невозможно выполнить с помощью sprintf и других связанных с строкой функций.
Ответ 4
Чтобы сделать это точно для обоих + ve и -ve номеров, вам необходимо использовать:
- функция php floor()
для + ve чисел
- функция php ceil()
для чисел -ve
function truncate_float($number, $decimals) {
$power = pow(10, $decimals);
if($number > 0){
return floor($number * $power) / $power;
} else {
return ceil($number * $power) / $power;
}
}
причина этого в том, что floor()
всегда округляет число вниз, а не к нулю.
т.е. floor()
эффективно округляет числа до большего абсолютного значения
например floor(1.5) = 1
, а floor(-1.5) = -2
Следовательно, для метода multiply by power, remove decimals, divide by power
truncate:
- floor()
работает только для положительных чисел
- ceil()
работает только для отрицательных чисел
Чтобы проверить это, скопируйте следующий код в редактор http://phpfiddle.org/lite (или аналогичный):
<div>Php Truncate Function</div>
<br>
<?php
function truncate_float($number, $places) {
$power = pow(10, $places);
if($number > 0){
return floor($number * $power) / $power;
} else {
return ceil($number * $power) / $power;
}
}
// demo
$lat = 52.4884;
$lng = -1.88651;
$lat_tr = truncate_float($lat, 3);
$lng_tr = truncate_float($lng, 3);
echo 'lat = ' . $lat . '<br>';
echo 'lat truncated = ' . $lat_tr . '<br>';
echo 'lat = ' . $lng . '<br>';
echo 'lat truncated = ' . $lng_tr . '<br><br>';
// demo of floor() on negatives
echo 'floor (1.5) = ' . floor(1.5) . '<br>';
echo 'floor (-1.5) = ' . floor(-1.5) . '<br>';
?>
Ответ 5
вы можете преобразовать 1.505
в тип данных String и использовать substring()
для усечения последнего символа.
И снова преобразуйте его в integer
.
Ответ 6
Используйте встроенную функцию PHP bcdiv.
Пример:
echo bcdiv(3.22871, 1, 1); // 3.2
echo bcdiv(3.22871, 1, 2); // 3.22
echo bcdiv(3.22871, 1, 3); // 3.228
echo bcdiv(-3.22871, 1, 1); // -3.2
echo bcdiv(-3.22871, 1, 2); // -3.22
Ответ 7
$num = 118.74999669307;
$cut = substr($num, 0, ((strpos($num, '.')+1)+2));`
// Cut the string from first character to a length of 2 past the decimal.
/ substr(cut what, start, ( (find position of decimal)+decimal itself)+spaces after decimal) )
echo $cut;
это поможет вам сократить значение поплавка, не округляя его.
Ответ 8
Ответы RenaPot, IsisCode, goredwards не верны.
Из-за того, как float работает в компьютерах (в целом), float не является точным.
Чтобы повторить проблему:
floor(19.99 * 100); // Outputs 1998 instead of 1999
floor( 5.10 * 100); // Outputs 509 instead of 510
В PHP внутри, 19.99 * 100
результатов в чем - то вроде 1998.999999999999999
, что когда мы делаем floor
из этого, мы получаем 1998
.
Решение:
Решение 1. Используйте библиотеку bcmath (предложенную @SamyMassoud), если она установлена (некоторые серверы общего хостинга могут не устанавливать ее по умолчанию). Вот так:
//floor(19.99 * 100);// Original
floor(bcmul(19.99, 100));// Outputs 1999
Решение 2: Манипуляции со строками (моя рекомендация):
// Works with positive and negative numbers, and integers and floats and strings
function withoutRounding($number, $total_decimals) {
$number = (string)$number;
if($number === '') {
$number = '0';
}
if(strpos($number, '.') === false) {
$number .= '.';
}
$number_arr = explode('.', $number);
$decimals = substr($number_arr[1], 0, $total_decimals);
if($decimals === false) {
$decimals = '0';
}
$return = '';
if($total_decimals == 0) {
$return = $number_arr[0];
} else {
if(strlen($decimals) < $total_decimals) {
$decimals = str_pad($decimals, $total_decimals, '0', STR_PAD_RIGHT);
}
$return = $number_arr[0] . '.' . $decimals;
}
return $return;
}
// How to use:
withoutRounding(19.99, 2);// Return "19.99"
withoutRounding(1.505, 2);// Return "1.50"
withoutRounding(5.1, 2);// Return "5.10"
Ответ 9
просто выполните (int) $number;
, чтобы получить целое число
Ответ 10
Я знаю, что это поздний ответ, но вот простое решение. Используя пример OP 1.505, вы можете просто использовать следующее, чтобы добраться до 1.50.
function truncateExtraDecimals($val, $precision) {
$pow = pow(10, $precision);
$precise = (int)($val * $pow);
return (float)($precise / $pow);
}
Это управляет как положительными, так и отрицательными значениями без необходимости фильтровать эту функцию для использования и дает возможность корректировать результаты, не беспокоясь о том, что другие функции могут делать со значением.
$val = 1.509;
$truncated = sprintf('%.2f', truncateExtraDecimals($val, 2));
echo "Result: {$truncated}";
Result: 1.50
Спринтf необходим для получения ровно 2 десятичных знаков для отображения в противном случае результат был бы 1,5 вместо 1.50.
Ответ 11
Мы можем использовать функции bc, если они доступны:
echo bcadd(sprintf('%F', 5.445), '0', 2); // => 5.44
echo sprintf('%.2F', 5.445); // => 5.45