Reg.ru: домены и хостинг

Крупнейший регистратор и хостинг-провайдер в России.

Более 2 миллионов доменных имен на обслуживании.

Продвижение, почта для домена, решения для бизнеса.

Более 700 тыс. клиентов по всему миру уже сделали свой выбор.

Перейти на сайт->

Бесплатный Курс "Практика HTML5 и CSS3"

Освойте бесплатно пошаговый видеокурс

по основам адаптивной верстки

на HTML5 и CSS3 с полного нуля.

Начать->

Фреймворк Bootstrap: быстрая адаптивная вёрстка

Пошаговый видеокурс по основам адаптивной верстки в фреймворке Bootstrap.

Научитесь верстать просто, быстро и качественно, используя мощный и практичный инструмент.

Верстайте на заказ и получайте деньги.

Получить в подарок->

Бесплатный курс "Сайт на WordPress"

Хотите освоить CMS WordPress?

Получите уроки по дизайну и верстке сайта на WordPress.

Научитесь работать с темами и нарезать макет.

Бесплатный видеокурс по рисованию дизайна сайта, его верстке и установке на CMS WordPress!

Получить в подарок->

*Наведите курсор мыши для приостановки прокрутки.


Сравнение и округление чисел с плавающей точкой

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


Сравнение чисел с плавающей точкой

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

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

Давайте сначала разберем правильное решение, после чего уже поговорим, почему следует делать именно так, а не иначе.

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

Как это выглядит в коде:


$delta = 0.00001;
$a = 1.0000000;
$b = 1.0000001;

if (abs($a - $b) < $delta)
{
    print '$a и $b можно считать равными с заданной степенью точности';
}

Почему же мы использовали такой неочевидный подход?

Дело в том, что в двоичном представлении чисел с плавающей точкой используется конечное число разрядом мантиcсы и экспоненты и при выходе за пределы разрядности происходит переполнение.

В результате PHP (а также некоторые другие языки) считает, что два равных числа различны, потому что они различаются в конечных разрядах.

Чтобы избежать подобных проблем, вместо проверки $a == $b следует проверить, отличается ли первое число от второго на очень малый интервал ($delta).

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

Ну и, наконец, для получения абсолютного значения разности мы используем функцию abs().


Округление чисел с плавающей точкой

Теперь давайте посмотрим, как можно округлять числа с плавающей точкой до целого числа или до заданного количества разрядов в дробной части.

Задача эта более, чем популярная, когда нам нужно рассчитать значения рейтингов, величину налогов, размер скидки и т.д.

Округление числа до ближайшего целого выполняется функцией round():


$number = round(2.4);
printf ("2.4 округляется до %s", $number);

Результат будет такой:


2.4 округляется до 2

Чтобы округление выполнилось в большую сторону, используйте функцию ceil():


$number = ceil(2.4);
printf ("2.4 округляется вверх до %s", $number);

Результат будет таким:


2.4 округляется вверх до 3

Округление в меньшую сторону осуществляется с помощью функции floor():

$number = floor(2.4);
printf ("2.4 округляется вниз до %s", $number);

Результат:

2.4 округляется вниз до 2

Отлично, с базовыми вещами разобралась. Теперь давайте рассмотрим некоторые частные моменты.

Если число находится ровно посередине между двумя числами, PHP округляет его в направлении от 0:


$number = round(2.5);
printf ("Округление положительного числа идет вверх до %s", $number);

echo "<br>";

$number = round(-2.5);
printf ("Округление отрицательного числа идет вниз до %s", $number);

Результат выполнения этого кода будет следующий:


Округление положительного числа идет вверх до 3
Округление отрицательного числа идет вниз до -3

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

Значение, которое на первый взгляд имеет дробную часть ".5", вместо этого может иметь дробную часть ".499999...9" (с длинной последовательностью девяток) или ".5000000...1" (с множеством нулей и завершающей единицей).

PHP автоматически включает небольшой "разброс" в вычислении с округлением, так что вам об этом беспокоиться не придется.

Для округления до заданного количества знаков в дробной части функция round() может получать необязательный аргумент. Допустим, вы вычисляете суммарную цену товаров в корзине покупателя:


$cart = 54.23;
$tax = $cart * .05;

$total = $cart + $tax;
$final = round($total,2);

print "При подсчете суммы налога используются все разряды: $total, но функция round() обрезает их до 2 знаков после целого числа: $final";

Результат будет таким:


При подсчете суммы налога используются все разряды: 56.9415,
но функция round() обрезает их до 2 знаков после целого числа: 56.94

Для округления числа в меньшую сторону используется функция floor():


$number1 = floor(2.1);  // floor(2.1) дает 2.0
$number2 = floor(2.9);  // floor(2.9) тоже дает 2.0
$number3 = floor(-2.1); // floor(-2.1) дает -3.0
$number4 = floor(-2.9); // floor(-2.9) тоже дает -3.0

Для округления числа в большую сторону используется функция ceil():


$number1 = ceil(2.1);  // ceil(2.1) дает 3.0
$number2 = ceil(2.9);  // ceil(2.9) тоже дает 3.0
$number3 = ceil(-2.1); // ceil(-2.1) дает -2.0
$number4 = ceil(-2.9); // ceil(-2.9) тоже дает -2.0

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

Успехов вам, и до связи!

Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!


Смотрите также:

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

CodeIgniter: жив или мертв?

CodeIgniter: жив или мертв?

Функции обратного вызова, анонимные функции и механизм замыканий

Функции обратного вызова, анонимные функции и механизм замыканий

Применение функции к каждому элементу массива

Применение функции к каждому элементу массива

Слияние массивов. Преобразование массива в строку

Слияние массивов. Преобразование массива в строку

Деструктор и копирование объектов с помощью метода __clone()

Деструктор и копирование объектов с помощью метода __clone()

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

PHP: Удаление элементов массива

PHP: Удаление элементов массива

Ключевое слово final (завершенные классы и методы в PHP)

Ключевое слово final (завершенные классы и методы в PHP)

50 классных сервисов, программ и сайтов для веб-разработчиков

50 классных сервисов, программ и сайтов для веб-разработчиков

Наверх