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

Удаление цифр после двух десятичных знаков без округления значения

У меня есть значение в переменной php вроде

$var='2.500000550';
echo $var

я хочу удалить все десятичные точки после двух цифр.

как сейчас значение переменной будет

$var='2.50';
echo $var

помните, что это значение исходит от mysql databse

но когда я использую round php function, я обернулся, но мне не нужен раунд, мне просто нужно удалить все цифры после двух десятичных простых.

Я устал, flot() и многие другие варианты не имеют успеха.

Спасибо

4b9b3361

Ответ 1

TL; DR:

Собственная функция PHP bcdiv, похоже, делает именно то, что требуется и правильно.

Чтобы просто "усечь" число, bcdiv($var, 1, 2);, где 2 - количество десятичных знаков для сохранения (и 1 - обозначение - деление числа на 1 позволяет просто обрезать исходный номер до нужных знаков после запятой)

Полный ответ (для истории)

Это оказывается более неуловимым, чем можно было бы подумать.

После того, как этот ответ был (неправильно) поддержан совсем немного, мне пришло в голову, что даже sprintf будет раунд.

Вместо того, чтобы удалять этот ответ, я превращаю его в более надежное объяснение/обсуждение каждого предлагаемого решения.

number_format - Неправильно. (Раундов)
Попробуйте использовать формат номера:

$var = number_format($var, 2, '.', '');  // Last two parameters are optional
echo $var;
// Outputs 2.50

Если вы хотите, чтобы это было число, просто введите тип float:

$var = (float)number_format($var, 2, '.', '');

Примечание:, как указано в комментариях, это фактически округляет число.

sprintf - неверно. (sprintf также раундов)
Если не округлить число, важно, то в ответе ниже используйте sprintf:

$var = sprintf("%01.2f", $var);

этаж - не совсем! (отрицательные числа округлых раундов)

floor, с некоторой математикой, приблизится к тому, что вы хотите:

floor(2.56789 * 100) / 100; // 2.56

Где 100 представляет точность, которую вы хотите. Если вы хотите, чтобы это было три цифры, то:

floor(2.56789 * 1000) / 1000; // 2.567

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

floor(-2.56789 * 100) / 100; // -2.57

"Старый" Правильный ответ: функция, использующая пол

Таким образом, для полностью надежного решения требуется функция:

function truncate_number( $number, $precision = 2) {
    // Zero causes issues, and no need to truncate
    if ( 0 == (int)$number ) {
        return $number;
    }
    // Are we negative?
    $negative = $number / abs($number);
    // Cast the number to a positive to solve rounding
    $number = abs($number);
    // Calculate precision number for dividing / multiplying
    $precision = pow(10, $precision);
    // Run the math, re-applying the negative value to ensure returns correctly negative / positive
    return floor( $number * $precision ) / $precision * $negative;
}

Результаты вышеуказанной функции:

echo truncate_number(2.56789, 1); // 2.5
echo truncate_number(2.56789);    // 2.56
echo truncate_number(2.56789, 3); // 2.567

echo truncate_number(-2.56789, 1); // -2.5
echo truncate_number(-2.56789);    // -2.56
echo truncate_number(-2.56789, 3); // -2.567

Новый правильный ответ

Используйте встроенную функцию PHP bcdiv

echo bcdiv(2.56789, 1, 1);  // 2.5
echo bcdiv(2.56789, 1, 2);  // 2.56
echo bcdiv(2.56789, 1, 3);  // 2.567
echo bcdiv(-2.56789, 1, 1); // -2.5
echo bcdiv(-2.56789, 1, 2); // -2.56
echo bcdiv(-2.56789, 1, 3); // -2.567

Ответ 2

floor(2.500000550 * 100) / 100;

Это должно выполнить вашу задачу...

Ответ 3

Вы запрашиваете функцию, которая возвращает "2.50" а не 2.5, поэтому здесь речь идет не об арифметике, а о манипулировании строками. Тогда preg_replace ваш друг:

$truncatedVar = preg_replace('/\.(\d{2}).*/', '.$1', $var);

// "2.500000050" -> "2.50", "2.509" -> "2.50", "-2.509" -> "2.50", "2.5" -> "2.5"

Если вы хотите сделать это с помощью арифметики, просто используйте:

$truncatedVar = round($var * 100) / 100);

// "2.500000050" -> "2.5", "2.599" -> "2.59", "-2.599" -> "2.59"

Ответ 4

попробуйте number_format:

echo number_format('2.50000050', 2); // 2.50

Ответ 5

использовать sprintf

sprintf("%01.2f", $var);

Ответ 6

number_format округляет число

php > echo number_format(128.20512820513, 2)."\n";
128.21

Я использовал preg_replace, чтобы действительно вырезать строку

php > echo preg_replace('/(\.\d\d).*/', '$1', 128.20512820513)."\n";
128.20

Ответ 7

кто-то разместил здесь

этаж (2.500000550 * 100)/100;

function cutAfterDot($number, $afterDot = 2){
$a = $number * pow(10, $afterDot);
$b = floor($a);
$c = pow(10, $afterDot);
echo "a $a, b $b, c $c<br/>";
return $b/$c ;
}
echo cutAfterDot(2.05,2);

a 205, b 204, c 100
2.04

поэтому в сыром виде не используйте его... Но если вы добавите немного эпсилон...

function cutAfterDot($number, $afterDot = 2){
        return floor($number * pow(10, $afterDot) + 0.00001) / pow(10, $afterDot);
    }

он работает!

Ответ 8

Используйте встроенную функцию 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

В вашем случае:

$var='2.500000550';
echo $var
echo bcdiv($var, 1, 2);  // 2.50

Ответ 9

Все решения, которые используют number_format, неверны, потому что number_format выполняет округление.

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

function truncate_decimal($number, $truncate_decimal_length = 2, $decimal_character = '.', $thousands_character = '') {

$number = explode($decimal_character, $number);
$number[1] = substr($number[1], 0, $truncate_decimal_length);
$number_truncated = implode($decimal_character, $number);
return number_format($number_truncated, $truncate_decimal_length, $decimal_character, $thousands_character);

}

Ответ 10

Следующее (что я считаю - пожалуйста, исправьте меня, если нет), надежное математическое решение, основанное в основном на информации от нескольких других ответчиков здесь, и небольшое количество от меня

(* Что не означает, что что-то не так с ответом на основе регулярного выражения Liphtier - просто я вижу, как пуристы хотят избежать регулярного выражения для того, что, возможно, является математическим проблема.)

  • sprintf(), number_format()round(), очевидно), все выполняют операцию округления, поэтому не подходят для обрезания без округления, запрошенного в вопросе (по крайней мере, не для них).
  • Вместо функции "из коробки" казалось бы самым элегантным решением было ответ Sujit Agarwal
  • Но из-за того, что хранятся поплавки, нам нужно использовать epsilon - как указано в ответе Дэвида Константина (где он также делает предыдущее решение более общим используя pow(), чтобы получить правильный коэффициент, основанный на заданной точности).
  • Но тогда, как указано в cale_b answer, любое использование floor() (или предположительно ceil()) может привести к непредвиденным результатам для негативов без использования abs().
  • И значение, которое я пытаюсь добавить:
    • Если вы используете деление на abs(), чтобы получить коэффициент отрицания, нам нужно учитывать особый случай, когда ввод равен 0.
    • Мы должны динамически создавать epsilon; Статический закодированный epsilon может быть слишком малым или слишком большим, в зависимости от требуемой точности. Я не видел эту проблему, рассмотренную в других ответах.

Используемый мной код:

public static function truncate_decimal($number, $leavePlaces = 2)
{
    if ($number == 0) return 0;
    $negate = $number / abs($number);
    $shiftFactor = pow(10, $leavePlaces);
    $epsilon = pow(10, -1 * $leavePlaces);
    return floor(abs($number) * $shiftFactor + $epsilon) / $shiftFactor * $negate;
}

Ответ 11

Простая функция, которая будет следовать, будет: "Если больше, чем 0 floor, else ceil", используя множитель для временного повышения его над десятичной точкой во время его выполнения:

function trim_num($num_in, $dec_places = 2) {
    $multiplier = pow(10, $dec_places); // 10, 100, 1000, etc
    if ($num_in > 0) {
        $num_out = floor($num_in * $multiplier) / $multiplier;
    } else {
        $num_out = ceil($num_in * $multiplier) / $multiplier;
    }
    return $num_out;
}

Ответ 12

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

Ответ 13

пол - не совсем! (пол округляет отрицательные числа)

Возможное решение из ответа cale_b.

static public function rateFloor($rate, $decimals)
{

    $div = "1" . str_repeat("0", $decimals);

    if ($rate > 0) {
        return floor($rate * $div) / $div;
    }

    $return = floor(abs($rate) * $div) / $div;

    return -($return);

}

static public function rateCeil($rate, $decimals)
{

    $div = "1" . str_repeat("0", $decimals);

    if ($rate > 0) {
        return ceil($rate * $div) / $div;
    }

    $return = ceil(abs($rate) * $div) / $div;

    return -($return);

}

положительный

Оценить: 0.00302471

Этаж: 0.00302400

Ceil: 0,00302500

отрицательный

Оценить: -0.00302471

Этаж: -0.00302400

Ceil: -0.00302500

Ответ 14

Если вы не хотите округлять число, но хотите удалить десятичные разряды, вы можете использовать метод "substr"

substr(string, start, length);
substr(4.96, 0, -1);