Skip to content

docs(tasks): 5245 asks for a remainder over the exact integer - #324

Closed
the-homeless-god wants to merge 1 commit into
devfrom
a/exact-remainder-task
Closed

the-homeless-god wants to merge 1 commit into
devfrom
a/exact-remainder-task

Conversation

@the-homeless-god

Copy link
Copy Markdown
Member

Заводит задачу 5245 — остаток и деление над точным целым. Повод пришёл от владельца: генетический алгоритм как пример нуждается в генераторе случайных чисел, а шаг любого линейного конгруэнтного генератора кончается на остаток от. Над точным целым его нет: задача 1908 определила плюс, минус, умножить на и пять слов порядка, а деление с остатком оставила названным отказом.

Что воспроизведено

Отказы — на двоичном задачи 1908, оба код 1:

над точным целым «mod» не определено: точное целое знает «плюс», «минус» и «умножить на»
над точным целым «div» не определено: точное целое знает «плюс», «минус» и «умножить на»

Потеря точности в число — против точных целых Python:

шаг число точно расхождение
Лемер, зерно 2 000 000 000, множитель 16807 33614000000000 33614000000000 0
glibc, зерно 2 000 000 000, множитель 1103515245, добавка 12345 2207030490000012300 2207030490000012345 45
glibc, зерно 1 234 567 891, тот же множитель и добавка 1362364488706010600 1362364488706010640 40

Две поправки, ради которых стоит прочитать задачу

Очевидная версия довода ложна. Произведение само по себе здесь точно: 2 000 000 000 · 1103515245 выше 2⁵³, но значащих бит в нём 51, и double держит его знак в знак. Ломает добавка — она сносит нижние нули. На полном ряду зёрен 2147483647 · 1103515245 + 12345 требует 60 значащих бит. Отсюда порог: множитель glibc выводит произведение за 2⁵³ при зерне 8 162 279 и выше, гарантированно точен лишь 0,38 % ряда по модулю 2³¹; множитель Лемера 16807 точен всюду (наибольшее произведение 2147483646 · 16807 = 36 092 757 638 322).

Задача исправляет мои же слова. В отчёте, закрывавшем 1908, я написал, что завершение разрядного деления держится на своей мере. Это неверно: в строках 608–699 bignum.flang нет ни одного убывает — «Биты разряда» убывает по счётчику, а два шаговых слова рекурсии не несут. Явная мера «Запас алгоритма Евклида» относится к НОД (строки 701–780). Цена деления, значит, в объёме (7 функций и 86 непустых строк против 1 функции и 23 у вычитания с займом), а не в доказательстве завершения. Число новых функций в задаче названо не меренным — оно зависит от нерешённого: нужен ли быстрый путь для делителя в один разряд.

Чего задача не закрывает

равен и не равен над точным целым сравнения не приводят — так решено в 1908 намеренно. Остаточный путь к неканоническому значению назван в задаче и закрывается сужением втекания список числа в точное целое, то есть задачей 1412 (она в поле рядом).

Проверки

  • run-script tasks:check — код 0: задач 203, свободно 189, в работе 8, сделано 6
  • task-numbers-guard --plan Check — код 0: открытых 203, занято закрытыми 401, двойных номеров 0
  • prose-numbers-guard --plan Check — 224 из 224 примет сходятся и с этим файлом, и без него, то есть ни одна счётная примета не сдвинулась (проверено прибором, а не арифметикой)

Правка только в docs/tasks/, компилятора не касается, перепечатка семени не нужна.

The exact integer got plus, minus, times and the five order words in task
1908; the remainder and the division were left as a named refusal. The owner
asked the question that makes the gap concrete: a genetic algorithm example
needs a random number generator, and every linear congruential generator
ends its step with "mod". So the refusal now has a case against it, and the
case is written down.

WHAT ACTUALLY LIES, named precisely, because the obvious version of this
argument is false. Reproduced on the binary of task 1908 against Python's own
exact integers:

  Lehmer, seed 2000000000, multiplier 16807        0 apart
  glibc,  seed 2000000000, mult 1103515245 + 12345 45 apart
  glibc,  seed 1234567891, same mult and increment 40 apart

The product ALONE is exact here: 2000000000 * 1103515245 is above 2^53, but
it needs only 51 significant bits and a double holds it digit for digit. The
INCREMENT is what breaks it - it clears the low zeros and the number then
needs more than 53 bits. On the full seed range it is worse: 2147483647 *
1103515245 + 12345 needs 60 significant bits.

Hence the corner the author is in: the glibc multiplier pushes the product
past 2^53 from seed 8162279 up, and only 0.38 percent of the range modulo
2^31 is still guaranteed exact. Lehmer's 16807 is exact everywhere - the
largest product over the whole range, 2147483646 * 16807, is 36092757638322
and below 2^53. So today the choice is Lehmer or silently wrong numbers.

THE COST SECTION CORRECTS MY OWN EARLIER CLAIM. I said in the report closing
1908 that division's termination rests on a measure of its own. It does not:
lines 608-699 of bignum.flang carry no "decreases" at all. "Bity razryada"
counts a non-negative counter down and the two step functions fold over a
fixed list of 22 bits. The explicit measure, "Zapas algoritma Evklida",
belongs to the GCD at lines 701-780, not to the division. So the cost here
is volume - 7 functions and 86 non-empty lines against 1 function and 23 for
subtraction with borrow - and not a termination proof. The task says so, and
says which of my own words were wrong, so the next reader does not inherit
the mix-up.

Three words from 1908 are reused rather than rewritten: "Umnozhit razryady
na maloe", "Raznost razryadov" and "Menshe razryadov" are exactly what the
bit step stands on. One trap is named with them: "Raznost razryadov" below
zero returns wrapped digits, not a refusal - the refusal lives one level up
in "Tochnoe vychitanie" - so guarding with "Menshe razryadov" before the
subtraction is the caller's duty.

The number of new functions is NOT measured and says so, because it depends
on a question nobody has answered yet: whether a fast path for a one-digit
divisor is wanted.

Measured, not predicted: run-script tasks:check code 0 (203 tasks, 189 free,
8 in work, 6 done), task-numbers-guard code 0 (203 open, 401 taken by closed
ones, 0 duplicates), prose-numbers-guard 224 of 224 marks agree both with
this file present and with it removed, so no counted mark moves.
@the-homeless-god

Copy link
Copy Markdown
Member Author

Closing as superseded: the remainder over exact integers is on dev (ADR-0062 item 7, f9a3de0; probe b1a8e9c), so task 5245 is no longer needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant