Целые и десятичные числа
В уроке 2 вы видели, что 25 / 2 даёт 12, а не 12.5. Этот подвох удивляет почти всех, поэтому давайте выясним, откуда он берётся и что с ним делать. Таблица для этого не нужна: SELECT без FROM просто вычисляет то, что вы ему дали, так что его можно использовать как калькулятор:
SELECT 7 / 2;| 7 / 2 |
|---|
| 3 |
Не 3.5, а 3. В SQLite есть два вида чисел: целые числа (тип INTEGER), например 7 или 40, и десятичные числа (тип REAL), например 3.5 или 40.0. Если оба числа в делении целые, то и результат целый, а всё, что шло бы после запятой, отбрасывается. Ничего не округляется вверх: 7 / 2 равно 3, 9 / 10 равно 0, а -7 / 2 равно -3. (Математики говорят, что результат округляется в сторону нуля.)
Как только одно из двух чисел десятичное, таким же будет и результат. Поэтому, когда нужен точный результат, запишите одно из чисел с .0:
SELECT 7 / 2.0, 7.0 / 2;| 7 / 2.0 | 7.0 / 2 |
|---|---|
| 3.5 | 3.5 |
Это важно в Pixel Shop, ведь цены там — целые числа (столбец price имеет тип INTEGER). Вот половина каждой цены, полученная делением на 2 и на 2.0:
SELECT title, price, price / 2 AS half_whole, price / 2.0 AS half
FROM games
LIMIT 3;| title | price | half_whole | half |
|---|---|---|---|
| Dragon Forge | 40 | 20 | 20.0 |
| Pixel Racer | 15 | 7 | 7.5 |
| Moon Farm | 20 | 10 | 10.0 |
Половина от $15 — это $7,50, но price / 2 говорит 7. Обратите внимание и на то, как SQLite записывает десятичные числа: 20.0 — десятичное число, которое просто оказалось целым, и .0 на это указывает. Длинные результаты показываются максимум с 15 цифрами: 10 / 3.0 даёт 3.33333333333333. В следующем упражнении вы научитесь их округлять.
Есть и другой способ: сначала умножить на 1.0: price * 1.0 / 2. Умножение на 1.0 не меняет значение, а только делает число десятичным. Так и стоит делать, когда оба числа в делении — столбцы, и добавить .0 некуда. Но умножать нужно в самом начале: в price / 2 * 1.0 деление уже отбросило половину, и вы получите 7.0.
Оператор % даёт остаток от деления нацело — то, что осталось. 135 минут — это 2 часа и 15 минут:
SELECT 135 / 60 AS hours, 135 % 60 AS minutes;| hours | minutes |
|---|---|
| 2 | 15 |
Так что деление нацело — не ошибка, а другой вид деления, и иногда это именно то, что нужно: часы и минуты, полные коробки и оставшиеся экземпляры, чётные и нечётные числа (id % 2 равно 0 для чётных ID и 1 для нечётных). Обратите внимание: % в SQL означает остаток, а не процент.
Типичная ошибка: проценты с целыми числами. 15 процентов от цены — это не price / 100 * 15: для любой цены меньше $100 выражение price / 100 равно 0, а значит, и весь результат равен 0. Пишите price * 15 / 100.0 или просто price * 0.15.
Задание
- 1
Pixel Shop хочет разрешить клиентам платить за игру четырьмя ежемесячными платежами. Покажите название, цену и цену, делённую на 4, как
installment, с десятичной частью. Отсортируйте игры по цене от самой высокой, а игры с одинаковой ценой — по названию:title price installment Knight's Oath 60 15.0 Goal Rush 50 12.5 Ice Hockey Pro 45 11.25 … … … - 2
Ниже добавьте запрос для подарочной карты магазина на $100: покажите название, цену, сколько экземпляров игры можно купить на карту, как
copies, и сколько долларов останется на карте, какleft_over. Отсортируйте игры по цене от самой низкой, а игры с одинаковой ценой — по названию:title price copies left_over Cube Logic 5 20 0 Word Quest 10 10 0 Bakery Story 15 6 10 … … … …