Один тов. задался вопросом: как 7 поделить на -5. Другой, недолго думая ответил: обнулить edx. Вот и у меня засело в башке и не даёт покоя такой вопрос, вернее несколько: 1. Для idiv 7/(-5) <> (-7)/5. Как с этим быть? 2. Как быть с таким: -(7/5). Куда знак лепить? К частному или остатку? И исходя из чего? 3. Написал такую процедурку, и не могу решить, оставить последний neg или убрать? Как правильней, подскажите. Код (Text): SignedDivision proc uses ebx ;на входе edx/eax - делимое (в пределах дворда), ecx - делитель ;на выходе eax - частное, edx - остаток, флаг C - деление на 0 mov ebx,1 test ecx,ecx jz @ZeroDiv jns @F neg ebx neg ecx @@: test eax,eax jns @F neg ebx neg eax @@: div ecx test ebx,ebx jns @F neg eax ;neg edx @@: clc ret @ZeroDiv: stc ret SignedDivision endp В отличие от idiv, процедура выдаёт одинаковый результат для 7/(-5) и для (-7)/5. Как в частном так и в остатке. Тот же idiv ведёт себя по разному, и взять его за образец невозможно. Так нужен neg edx или нет? Имеет ли смысл знак применительно к остатку?
А вообще, вопрос интересный. Посмотри во 2м томе команды FPU FPREM и FPREM1 - они обе вычисляют остаток, только он тоже разный .
Вот чтобы уйти от неоднозначности и написал процедуру. А в какую сторону повернуть однозначность? Имхо, более логичным мне кажется без neg edx, т.е. остаток не может быть со знаком. С другой стороны, лезут сомнения, не позволяющие поставить точку: может чего упустил из виду, какие-нибудь подводные камни?
Я про мануал к чему говорил. Там есть такая формула: Даны числа A и B Остаток (A / B) = A - (Q * B) Где Q = Округление (A / B) Так вот, уже от того, как округляется (A / B) зависит значение Остатка. Поэтому и есть 2 команды - результат их различен.
К сожалению, я не знаю, о каком мануале идёт речь А формулы эти вообще выдают 4 варианта остатка (в зависимости от способа округления и знаков входных данных). А=7, В=-5 Q=-1 либо Q=-2 Остаток = 2 либо -3 А=-7, В=5 Q=-1 либо Q=-2 Остаток = -2 либо 3 Я же как раз хочу уйти от этой неоднозначности, делаю, что остаток всегда 2 (согласно логике). Только никак не решу, должен ли знак частного распространяться на остаток, или нет.
Вот и у меня засело в башке и не даёт покоя такой вопрос, вернее несколько: 1. Для idiv 7/(-5) <> (-7)/5. Как с этим быть? А чем тебя не устраивает работа idiv. Работает она правильно, как и ожидают все нормальные люди. Вот делишь ты 7/(-5) и получаешь частное -1 и оснаток 2 (так как 7 - число положительное, то естественно и остаток положителен) А если делишь (-7)/5, то получаешь частное -1 и остаток -2 (так как -7 - число отрицательное, то естественно и остаток отрицателен) Не надо путать остаток от знакового деления и модуль остатка от знакового деления, это разные вещи.
Julius Это говорит о том, что ты даже и не пробовал. А когда попробуешь, то возможно и заметишь, что остаток вовсе и не -2, а очень даже 4 xor edx,edx mov eax,-7 mov ecx,5 idiv ecx PrintDec edx и нарисуется edx = 4. Вот этим и не устраивает меня idiv. 4 вообще как пришить к этому делу??? P.S. за ненормального спасибо
Это говорит о том, что ты даже и не пробовал. А когда попробуешь, то возможно и заметишь, что остаток вовсе и не -2, а очень даже 4 Прошу прощения, но это говорит о том, что ты не правильно написал программу. xor edx,edx mov eax,-7 mov ecx,5 idiv ecx Здесь ты делишь не -7/5, а 00000000fffffff9/5 а правильно надо делать, например, так mov edx,-1 mov eax,-7 mov ecx,5 idiv ecx Ибо ты делишь 64 битное знаковое число. Расширение знаком еще никто не отменял. за ненормального спасибо Без абид, это просто такой словестный оборот.
cresta Julius и Black_mirror правы на 100%. Стоит заглянуть в IA-32, чтобы убедиться в том что: 1) Делимое в IDIV всегда содержится в (E)DXE)AX. Если ты кидаешь свое число в EAX, то EDX должно быть знаковым расширением EAX, т.е. 0 при EAX >= 0 и -1 при EAX < 0. Инструкции CWD и CDQ именно для этого и предназначены - они заполняют (E)DX знаковым битом (E)AX. 2) Знак остатка всегда равен знаку делимого а "округление" результата, о котором говорил S_Т_A_S_, всегда осуществляется в сторону 0, т.е. произведение частного на делитель по модулю всегда меньше делимого. Именно поэтому остаток и называется "остатком", а не избытком или еще чем. Код (Text): 7/(-5) = (5+2)/(-5) = -1 + 2/(-5) = -1 и +2 в остатке (-7)/5 = (-5-2)/5 = -1 + (-2)/5 = -1 и -2 в остатке т.е. остатки имеют разные знаки, но с учетом знака делителя результат получается один и тотже "минус одна целая и две пятых".
leo Вот это похоже, самое главное. А то, что знак остатка всегда равен знаку делимого, как мне кажется только усложняет жизнь. Если например, я хочу работать с остатком как с беззнаковым, то вынужден проверять его (либо частное) на знак. И соответственно корректировать. Согласен, для машины может в каких-то (или во всех) случаях логично, что остаток может иметь знак, но программу то пишет не машина... Если такая абстрактная задача: поделить кучу чисел и суммировать остатки, то для 7/-5 и -7/5 в итоге окажется, что никакого остатка и нет вовсе. Что на мой взгляд неправильно. Да собственно та процедура, что описана в вопросе, это попытка уйти от машинной логики к логике человеческой.
cresta > "уйти от машинной логики к логике человеческой" Знаковый остаток - это как раз не машинная, а человеческая логика, реализованная в машине. Вспомним Лису Алису из детского фильма: -7 на 5 не делится ? не делится, тогда возьмем ближайшее меньшее (по модулю), которое делится, это -5. Получим результат = -1. А остаток это есть разница между тем что требовалось разделить (-7) и тем "меньшим" что мы взяли (-5), т.е. -2. Вся ясно, логично и однозначно. Резюме: знаковый остаток - это не прихоти "машины", а правила математики. Если в какой-то задаче нужно брать модуль остатка, то тут ничего не поделаешь, придется проверять знак и корректировать, если нужно.
leo > Вот как раз не всегда ТОт остаток, о котором говорилось не соответствеут стандарту IEEE 754. В книгах двойных слов (IA-32 Intel® Architecture Software Developer’s Manual Volume 2A: Instruction Set Reference) рассказано о такой инструкции: FPREM1—Partial Remainder
Эй, Вы, гуру!!! Ну посоветуйте что-нибудь в конце-то концов! А то я уже запутался окончательно и бесповоротно (( Кого слушать-то???
Теорема. Для данного целого отличного от нуля числа b, всякое целое число а единственным образом представимо в виде а = bq + r , где 0 <= r < |b|. Определение. Число q называется неполным частным, а число r — остатком от деления а на b . Заметим, дорогие читатели, что остаток — всегда есть число неотрицательное, а вот неполное частное может быть каким угодно целым числом. Поэтому на вопрос: “Сколько будет минус пять поделить на три с остатком?”, каждый должен бойко отвечать: “Минус два, в остатке — один!”. Но за добрый десяток лет опыта приема устных вступительных экзаменов в университет, судьба еще не послала мне абитуриента, правильно ответившего на этот вопрос. А ведь это дети, специально готовившие себя поступать именно на математико-механический факультет. “Печально я гляжу на наше поколение...” ЛЮБОМУ, кто скажет тебе, что остаток - число отрицательное - плюнь в лицо.
Да уж... Час от часу не легче. Теперь -5/3 = -2 и в остатке один.... А -7/5 значит должно быть -2(частное) и 3 (остаток). Всё это напоминает анекдот про того еврея, ответившего на вопрос "Сколько будет дважды два?" естественно вопросом: "А сколько Вам надо?" Итого имеем уже семь разных вариантов
Еще раз - если мы говорим об остатке от целочисленного деления тут двух мнений быть не может. Одно мое, другое неправильное А правила теории чисел не мной и не вчера выдуманы.