День 03 · Типы и арифметика · страница 2 из 6

Арифметика целых чисел

Склад считает в штуках: товары, коробки, заказы, копейки. Это целые числа, и у их арифметики в Go есть особенность — деление.


Пять операторов

Ситуация. На складе 17 товаров, в коробку помещается 5: сколько будет полных коробок и сколько товаров останется?

Код для чтения · разбираем, набирать не нужно
package main

import "fmt"

func main() {
	fmt.Println(17 + 5)
	fmt.Println(17 - 5)
	fmt.Println(17 * 5)
	fmt.Println(17 / 5)
	fmt.Println(17 % 5)
}

Что увидите.

Пример · только посмотреть, набирать не нужно
stagiaire@lab:~/gocourse/day03/scratch$ go run .
22
12
85
3
2

Как это читать. Сложение, вычитание и умножение — как в школе. / у целых чисел даёт целую часть деления, % — остаток: 17 / 5 — три полные коробки, 17 % 5 — два товара без коробки (3 * 5 + 2 = 17).


Целое деление отбрасывает дробь

В математике 17 / 5 = 3.4. В Go, если оба числа целые, результат тоже целый, и дробь отбрасывается, а не округляется: 3.8 тоже стало бы 3. С отрицательными числами отбрасывание идёт к нулю:

Код для чтения · разбираем, набирать не нужно
	fmt.Println(-7/2, -7%2, 7/-2, 7%-2)
Вывод · это печатает программа, набирать не нужно
-3 -1 -3 1

-7 / 2 в математике -3.5; дробь отброшена — вышло -3, а не -4. Остаток такой, чтобы сходилась проверка «частное × делитель + остаток = делимое»: -3 * 2 + (-1) = -7. Отсюда правило: знак остатка — как у делимого. Складу дробь и не нужна: 3.4 коробки не бывает.


Попробуйте сейчас: что выведет деление целых?

Цель: предсказать вывод деления и остатка без запуска и отправить ответ.

Предскажите вывод, не запуская:

Код для чтения · разбираем, набирать не нужно
package main

import "fmt"

func main() {
	fmt.Println(9/4, 9%4, -9/4)
}
▶ Выполните · выделенное замените своим
course answer day03.q1 ВАШ_ОТВЕТ

Вместо ВАШ_ОТВЕТ — строка вывода целиком, как её напечатает программа.

После ответа проверьте себя запуском — программу нужно набрать в scratch/main.go:

✎ Наберите в файл scratch/main.go
package main

import "fmt"

func main() {
	fmt.Println(9/4, 9%4, -9/4)
}
▶ Выполните
cd ~/gocourse/day03/scratch
go run .

Разошлось с вашим ответом — отправьте ответ заново, засчитывается последний.

Готово, когда: ответ отправлен — пункт проверки q1.


Порядок действий

Как в школе: сначала скобки, потом *, / и % слева направо, потом + и -.

Код для чтения · разбираем, набирать не нужно
	fmt.Println(2+3*4, (2+3)*4)
	fmt.Println(100-20*3/4, 7*10/4, 7/4*10)
Вывод · это печатает программа, набирать не нужно
14 20
85 17 10

Как это читать.

Выражение Шаги Итог
2+3*4 3*4 = 12, 2+12 14
(2+3)*4 скобки: 5, 5*4 20
100-20*3/4 20*3 = 60, 60/4 = 15, 100-15 85
7*10/4 7*10 = 70, 70/4 — это 17.5, дробь отброшена 17
7/4*10 7/4 — это 1.75, дробь отброшена: 1, 1*10 10

Последние два выражения отличаются только порядком — и дают 17 и 10: в 7/4*10 дробь потерялась в середине расчёта, и умножение её не вернёт. Отсюда правило, которое понадобится на пятой странице: сначала умножать, потом делить. Пробелы вокруг операторов ставит gofmt, на результат влияют только скобки.


Попробуйте сейчас: что выведет порядок действий?

Цель: предсказать вывод с порядком действий и отправить ответ.

Код для чтения · разбираем, набирать не нужно
package main

import "fmt"

func main() {
	items := 50
	fmt.Println(items-8*3/4, (items-8)*3/4)
}
▶ Выполните · выделенное замените своим
course answer day03.q2 ВАШ_ОТВЕТ

Вместо ВАШ_ОТВЕТ — строка вывода целиком.

После ответа проверьте себя запуском — программу нужно набрать в scratch/main.go:

✎ Наберите в файл scratch/main.go
package main

import "fmt"

func main() {
	items := 50
	fmt.Println(items-8*3/4, (items-8)*3/4)
}
▶ Выполните
cd ~/gocourse/day03/scratch
go run .

Разошлось — отправьте ответ заново, засчитывается последний.

Готово, когда: ответ отправлен — пункт проверки q2.


Рубли и копейки

Цены в курсе хранятся в копейках, целым числом (почему — на пятой странице), а рубли и копейки достаются делением и остатком:

Код для чтения · разбираем, набирать не нужно
	price := 12305
	fmt.Println(price/100, "руб.", price%100, "коп.")
Вывод · это печатает программа, набирать не нужно
123 руб. 5 коп.

12305 / 100 — сколько целых сотен копеек, то есть рублей, 12305 % 100 — что осталось. На чеке пишут «05 коп.»: как напечатать ведущий ноль — на четвёртой странице.


Трассировка с арифметикой

Таблица трассировки из дня 02 показывает по шагам, что лежит в переменных.

Код для чтения · разбираем, набирать не нужно
package main

import "fmt"

func main() {
	stock := 250
	orders := 7
	perOrder := stock / orders
	left := stock % orders
	stock = stock - perOrder*orders
	fmt.Println(perOrder, left, stock)
}

Номер строки считается от начала файла, включая пустые: package main — строка 1, stock := 250 — строка 6; если первой строкой стоит комментарий, как в trace/main.go, номера сдвигаются на одну.

Формат — из дня 02: шапка-комментарий с #, колонка на каждую переменную, строка таблицы на каждую выполненную строку main, включая печать:

Образец · набирать не нужно
# шаг | строка | stock | orders | perOrder | left
1 | 6  | 250 | - | -  | -
2 | 7  | 250 | 7 | -  | -
3 | 8  | 250 | 7 | 35 | -
4 | 9  | 250 | 7 | 35 | 5
5 | 10 | 5   | 7 | 35 | 5
6 | 11 | 5   | 7 | 35 | 5

Как это читать. В колонке — что лежит в переменной после строки, - — переменной ещё нет. Шаг 3: 250 / 7 — это 35.7…, дробь отброшена. Шаг 4: 35 * 7 = 245, до 250 не хватает 5. Шаг 5: справа от = берётся старое значение stock, 250. Шаг 6 — печать: значения переписаны из шага 5.


Что может пойти не так

Что видите Что это значит Что делать
получилось 10, ожидали 17 деление раньше умножения, дробь потеряна в середине сначала умножить, потом делить
получилось 14, ожидали 20 умножение раньше сложения поставить скобки
Все ? заполнены, но где-то значение не совпало ошибка в шаге: часто в колонке, которую шаг не менял, или на строке печати несменившиеся значения переписать из строки выше
Строк с шагами в таблице 8, а нужно 7 строку удалили, добавили или сняли # с шапки меняются только ?

Попробуйте сейчас: задание boxes.

Цель: boxes/main.go сама считает коробки и остаток по числам из TASK.txt.

  1. Прочитайте условие — числа у вас свои:
▶ Выполните
cd ~/gocourse/day03/boxes
cat TASK.txt
  1. Создайте в папке boxes файл main.go: числа из условия — в переменные, коробки и остаток — выражения из них. Проверка подставит в копию другие числа, и готовые ответы не пройдут.
  2. Запустите и сравните вывод с примером из TASK.txt:
▶ Выполните
go run .

Готово, когда: вывод совпал с примером из TASK.txt строка в строку — пункт boxes.


Попробуйте сейчас: трассировка задания trace.

Цель: в trace/table.txt все ? заменены значениями, найденными без запуска.

  1. Посмотрите программу — числа в ней ваши:
▶ Выполните
cd ~/gocourse/day03/trace
cat main.go
  1. Откройте table.txt в VS Code: шаги, номера строк и прочерки вписаны — замените каждый ? значением переменной после строки, в уме, без запуска. Особое внимание шагу 4.
  2. Номера строк — по main.go как он лежит, поэтому файл не меняйте; отладочную печать добавляйте в копию:
▶ Выполните
cp main.go ~/gocourse/day03/scratch/main.go
  1. Заполнив таблицу, запустите программу: rub и kop из последней строки должны совпасть с выводом.
▶ Выполните
cd ~/gocourse/day03/trace
go run .

Готово, когда: в table.txt не осталось ?, а rub и kop из последней строки совпали с выводом — пункт trace.


Дальше: дробные числа и преобразования типов — course next