Як і в інших мовах, числа в PHP представлені в двійковій системі (системі одиниць і нулів), тому деякі математичні операції можуть давати дещо інші результати, ніж можна було б очікувати. На цій сторінці наведено огляд поведінки обчислень у різних контекстах. Для розуміння потрібні принаймні базові знання про **числові методи** та **системи числення**.
Спосіб представлення чисел характеризується типом даних, наприклад, ціле число перетворюється безпосередньо з вихідного коду з десяткової системи числення в двійкову. Нам взагалі не потрібно турбуватися про конвертацію цифр, все робиться автоматично.
Наслідком такого перетворення є те, що максимальне значення цілого числа визначається кількістю розрядів, доступних в пам'яті. На 32-бітному PHP діапазон від -2 147 483 648
до -2 147 483 647
(~ ± 2 мільярди), на 64-бітному PHP діапазон від -9 223 372 036 854 775 808
до -9 223 372 036 854 775 807
(~ ± 9 квінтильйонів). Максимальне значення завжди можна отримати, викликавши константу PHP_INT_MAX
.
Десяткові числа зберігаються в типі даних float, який має обмежену точність, тому зберігається внутрішньо у вигляді пари чисел, до яких застосовується математична операція мантиса * (2^експонента)
. Практичним наслідком є те, що ми можемо зберігати відносно велику кількість (порядку мільярдів) в невеликій кількості бітів, просто не дуже точно.
Наслідком використання типу даних float є те, що результат обчислення 1 - 0,9
не є точно 0,1
.
Приклад з веб-форумів:
$x = 0.3;$y = 0.4;echo 0.7 - $x - $y; // prints -5.5511151231258E-17
Якщо трохи підкоригувати цифри:
$x = 6.5;$y = 7.5;echo 14.0 - $x - $y; // виводить 0
Взагалі це питання обговорюється в окремій статті на VTM.e15.cz: Чому комп'ютери мають проблеми з десятковими числами, або взагалі про плаваючу крапку у Вікіпедії.
Як правило, бажано округляти результат після обчислення або взагалі уникати десяткових знаків. Наприклад, зберігати ціну не в кронах (як 14,90), а в копійках (як 1490) і потім працювати саме з нею. Округлення обговорюється в наступному розділі цієї статті.
$a = 5;$b = 3;echo $a + $b;
Для операцій можуть використовуватися загальноприйняті математичні конвенції, які поважають пріоритет операторів згідно з правилами математики (множення має пріоритет над додаванням і т.д.). Значення можуть бути записані безпосередньо або прочитані через змінні.
Можливо, це не очевидно на перший погляд, але в математичному прикладі не написано знак рівності (
=
). Звідси випливає, що розв'язувати можна лише прості "бінарні операції", які завжди працюють лише з "двома елементами" (рівняння не рахувати, для цього треба використовувати спеціалізовану бібліотеку).
У колонці "результат" я перераховую, що буде надруковано в припущенні:
$a = 5;$b = 3;$c = 10;
Операція | Позначення | Позначення словами | Приклад позначення | Результат |
---|---|---|---|---|
Додавання | + |
Плюс | echo $a + $b; |
8 |
Віднімання | - |
Мінус | echo $a - $b; |
2 |
Множення | * |
Зірочка | echo $a * $b; |
15 |
поділ | / |
коса риска | echo $a / $b; |
1.666666666666667 |
дужки | ( ) |
дужки | echo $a + ($b * $c); |
35 |
Конкатенація рядків | . |
Крапка | echo $a . $b . $c; |
5310 |
Залишок після ділення | % |
Відсоток | echo $a % $b; |
2 |
Додавання одного | ++ |
двох плюсів | echo $a++; |
6 |
Відняти один мінус два мінус чотири. | ||||
Сила - дві зірочки - відлуння $a ** $b; | 125 |
Оператор степеня (подвійна зірочка) доступний тільки починаючи з версії PHP 7.1. В інших версіях PHP необхідно використовувати універсальну функцію
pow($a, $b)
.
Якщо ви вирішуєте якусь поширену обчислювальну задачу, то швидше за все вже є функція безпосередньо в PHP, ось анотований огляд їх.
Звичайне округлення виконується функцією round(), вона має 3 параметри:
round(5); // 5round(5.1); // 5round(5.4); // 5round(5.5); // 6round(5.8); // 6round(5483.47621, 2); // 5483.47round(5483.47621, -2); // 5500
Існує також функція floor() для округлення в меншу сторону і ceil() для округлення в більшу сторону.
Обережно, типи даних!
Всі функції округлення повертають результат як
float
, навіть якщо результат є цілим числом.Якщо ви хочете обробляти результат як ціле число, важливо переписати результат після цього. Наприклад:
echo (int) round(3.14);
.
PHP працює з різними типами даних, наприклад з float легко може статися так, що результатом функції round()
буде не число з кінцевим десятковим розкладанням. Для лістингу рекомендую використовувати функцію number_format()
, про яку я розповім нижче.
Вони використовуються для багатьох різних розрахунків і базуються на одиничному колі. Вони використовуються, наприклад, при побудові кіл, еліпсів, переміщень тощо.
Обчислити кут від x
і y
. Перетворення декартових і полярних координат.
На основі одиничної гіперболи. Їх визначення можна легко описати, використовуючи приклади:
Вони використовуються, наприклад, для генерації рельєфу місцевості та фізичного моделювання.
На основі одиничної гіперболи.
echo sin(30); // -0.98803162409286echo sin(deg2rad(30)); // 0.5echo cos(deg2rad(123)); // -0.54463903501503echo 1/tan(deg2rad(45)); // 1 (один котангенс)echo sin(deg2rad(500)); // 0.64278760968654echo atan2(deg2rad(50), deg2rad(23)); // 1.1396575860761
Іноді може статися так, що нам потрібно обробити математичний вираз у вигляді рядка користувача, наприклад 5+2^(1+3/2)
.
Не існує простого способу обробки такого вводу в PHP, але я запрограмував ряд бібліотек, які вирішують цю проблему.
Детальніше дивіться в окремій статті Калькулятор на PHP: Обробка математичного виразу у вигляді рядка.
Великі числа і десяткові знаки в PHP зберігаються як числа з плаваючою комою, плюс вони округляються приблизно до 15 знаків після коми, що іноді може дратувати. Саме тому було створено бібліотеку довільної прецизійної математики BCMath.
Числа в цій бібліотеці представлені як строки, тому вони не обмежені неточністю float, але операції, що виконуються, відбуваються на кілька порядків повільніше (але все одно швидше, ніж якби ми запрограмували таку функцію самостійно).
Наприклад, якщо ми хочемо отримати квадратний корінь з 2 до 3 знаків після коми, ми просто викликаємо:
echo bcsqrt('2', 3); // 1.414
Jan Barášek Více o autorovi
Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.
Rád vám pomůžu:
Články píše Jan Barášek © 2009-2024 | Kontakt | Mapa webu
Status | Aktualizováno: ... | uk