openlang

round(2.5) даёт 2, и ученики не верят

Ученики упорно думают, что round(2.5) равно 3, а оба языка, к которым я обычно тянусь, говорят 2. Python даёт целое 2, Julia даёт 2.0. Оба отправляют ничью к чётному соседу, так что round(0.5) равно 0, а round(1.5) равно 2, и закономерность видна, только когда несколько ничьих стоят рядом.

print([round(x) for x in (0.5, 1.5, 2.5, 3.5)])

Это печатает [0, 2, 2, 4], и Julia даёт те же значения, только с плавающей точкой. Моя догадка в том, что четыре ничьи сразу учат лучше, чем формулировка правила, ведь сломанной выглядит именно двойка рядом с другой двойкой, и тогда вопрос превращается в «кому это вообще нужно».

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

Разговор продолжается 4

Следуя доводам
  1. Ссылка на ответ

    Ответ на «зачем» - это подсчёт. Сложите четыре ничьи точно, получится 8. Округлите сначала половины вверх, получится 1 + 2 + 3 + 4 = 10. Округлите к чётному, получится 0 + 2 + 2 + 4 = 8. Округление вверх толкает каждую ничью в одну сторону, и ошибка растёт с числом ничьих. К чётному отправляет половину в каждую сторону, и в среднем всё гасится. Ученик, который переходит между языками, встретит оба варианта, ведь math.Round в Go округляет половины от нуля, а math.RoundToEven - отдельная функция.

  2. Ссылка на ответ

    Одну вещь, мне кажется, стоит держать отдельно от этого урока. round(2.675, 2) в Python даёт 2.67, и ученики относят это к тому же сюрпризу, но причина другая. Ближайшее к 2.675 число с плавающей точкой лежит чуть ниже, так что никакой ничьей нет вовсе, и документация Python приводит ровно этот пример. Поэтому сначала ничьи, на значениях, точных в двоичной записи, вроде 0.5 и 2.5, а представление чисел вторым шагом.

    from decimal import Decimal, ROUND_HALF_UP
    print(Decimal(2.675))
    print(Decimal('2.675').quantize(Decimal('0.01'), rounding=ROUND_HALF_UP))

    Первая строка показывает хранимое значение, 2.67499999999999982236431605997495353221893310546875. Вторая даёт 2.68, потому что строка сохраняет то десятичное значение, которое ученик действительно набрал.

  3. Ссылка на ответ

    round(-0.5) в Python даёт целое 0, а round(-0.5, 0) и round(-0.5) в Julia дают -0.0. Никто этого не замечает, пока Julia не поделит на него и не вернёт -Inf.

Другие стороны того же вопроса

  1. 3 + 4 * 2 равно 14, и это ещё простая часть

    Каждый, кто начинает со Smalltalk, рано встречает 3 + 4 * 2 и слышит, что это 14, потому что бинарные сообщения идут слева на…

    Ответы 1smalltalk
  2. Ручной перевод старого CoffeeScript как урок JavaScript

    Немодное упражнение, которое работает лучше, чем имеет на то право. Дайте ученику небольшой старый файл на CoffeeScript и поп…

  3. (x, x) не значит, что обе половины равны

    Ученики раз за разом читают (x, x) в OCaml как «обе половины равны». Это не так, и такой паттерн вообще недопустим. Новичок о…

    Ответы 5ocaml