spamsink: (lenin)
[personal profile] spamsink

Встретился мне вдруг код, реализующий целочисленное (2's complement) деление со знаком, в котором INT_MIN / -1 == INT_MAX, INT_MIN % -1 == -1, причем не по ошибке, а совершенно намеренно, но без комментария, откуда взялся резон для такого решения. Никто не в курсе, где такое было?

Date: 2014-06-11 03:47 am (UTC)
From: [identity profile] archaicos.livejournal.com
Что-то как-то странно.

Если модули INT_MIN и INT_MAX равны, то это какой-то неправильный (OK, нетрадиционный) код дополнения до двух. Обычно модули равны если представление целых со знаком одно из следующих:
- код дополнения до 1 (все биты инвертируют для обращения знака, и для лулзов имеем +0 и -0)
- бит знакак и модуль (возможны те же лулзы)

Мне кажется, что ты имеешь дело с UB, реализованное таким конкретным способом, т.к. -INT_MIN в честном коде дополнения до 2 не представим (не отличим от +INT_MIN).

Date: 2014-06-11 04:40 am (UTC)
From: [identity profile] archaicos.livejournal.com
В приведённом примере деление не может дать частное в том же типе int, ибо не лезет. Переполнение выражения целочисленного типа со знаком — UB по определению стандарта языка. Это что касается INT_MIN / -1 == INT_MAX.

С INT_MIN % -1 == -1 дело интересней. Остаток может быть и можно было посчитать честно, т.к. он лезет в int, но поскольку он типично является побочным продуктом вычисления частного от деления, то на практике тоже получается «ой». По хорошему, стандарту стоило прописать этот случай в явном виде. Но сразу это не было сделано (в оригиинальной версии стандарта от 99-го года этого нет).

Зато есть в ISO/IEC 9899:201x Committee Draft — April 12, 2011 N1570:

6 When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded. 105) If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a; otherwise, the behavior of both a/b and a%b is undefined.
Edited Date: 2014-06-11 04:42 am (UTC)

Date: 2014-06-11 04:54 am (UTC)
From: [identity profile] archaicos.livejournal.com
Тогда не используй INT_MIN, INT_MAX и п.р. чтобы не вводить в заблуждение лишний раз. :)

Date: 2014-06-11 03:50 am (UTC)
From: [identity profile] panchul.livejournal.com
Для 2's complement это просто неверно. Или как?

Date: 2014-06-11 03:53 am (UTC)
From: [identity profile] yatur.livejournal.com
Может, они хотели, чтобы выполнялась формула

a == (a/b)*b + (a%b)?

Для 16 бит, a = -32768, b = -1
-32768 == 32767*-1 + (-1).

Date: 2014-06-11 04:57 am (UTC)
vak: (Default)
From: [personal profile] vak
В определенном смысле это логично.
INT_MIN/-1 непредставимо, и лучшим приближением будет INT_MAX.
А остаток вычисляется вычитанием второго из первого: INT_MIN - INT_MAX*-1 = -1.

Date: 2014-06-11 05:40 am (UTC)
ext_659502: (Default)
From: [identity profile] some41.livejournal.com
обычно арифметические операции возвращают не "лучшее представление" (т.е. насыщение), а truncation (т.е. младшие биты результата). с этой точки зрения должно быть INT_MIN / -1 == 0 (и то же самое с умножением INT_MIN * -1). правда не очень понятно с остатком -- truncation дает 0, а вывод через r = D - d*q дает INT_MIN.

Date: 2014-06-11 02:32 pm (UTC)
ext_659502: (Default)
From: [identity profile] some41.livejournal.com
Ерунду написал. Truncation как раз даёт INT_MIN / -1 == INT_MIN.

Date: 2014-06-11 06:24 am (UTC)
vak: (Default)
From: [personal profile] vak
Трудно сказать, я такого по жизни не встречал. В случае MIPS архитектура не определяет результат деления INT_MIN на -1. То есть на усмотрение разработчика. Реальные процессоры выдают результат INT_MIN. Что совсем нелогично, но факт.

Date: 2014-06-11 06:11 pm (UTC)
From: [identity profile] sab123.livejournal.com
Это, видимо, арифметика "с насыщением", где INT_MIN и INT_MAX служат минус бесконечностью и плюс бесконечностью. Небось полезна в каком-нибудь DSP?

Date: 2014-06-11 06:44 pm (UTC)
From: [identity profile] sab123.livejournal.com
Ну вот вроде ж плавающие числа подобным реализованы почти везде (IEEE стандарт, происходящий от Интела). А это может аналогичная реализация для fixed point. Хотя прям конкретного железа я конечно не знаю, да и область не моя.

Date: 2014-06-11 05:32 am (UTC)
ext_659502: (Default)
From: [identity profile] some41.livejournal.com
понятно, что идеального варианта здесь нет. для объективного сравнения нужно выписать набор полезных свойств операций / и %, и посмотреть, какой вариант сохраняет "больше". например,
forall x < 0, y < 0: x / y >= 0
forall x: x % -1 == 0
forall x: abs(x / -1) == abs(x)
forall x: x / -1 == x * -1

Date: 2014-06-11 12:38 pm (UTC)
ext_659502: (Default)
From: [identity profile] some41.livejournal.com
Безусловно, веса могут быть разные. Последнее свойство говорит, что деление нужно согласовывать с умножением: если INT_MIN / -1 == INT_MAX, то и INT_MIN * -1 == INT_MAX.
Edited Date: 2014-06-11 12:39 pm (UTC)
Page generated Mar. 7th, 2026 08:12 pm
Powered by Dreamwidth Studios