7/(-5) <> (-7)/5

Тема в разделе "WASM.A&O", создана пользователем cresta, 27 ноя 2004.

  1. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Один тов. задался вопросом: как 7 поделить на -5. Другой, недолго думая ответил: обнулить edx. Вот и у меня засело в башке и не даёт покоя такой вопрос, вернее несколько:

    1. Для idiv 7/(-5) <> (-7)/5. Как с этим быть?

    2. Как быть с таким: -(7/5). Куда знак лепить? К частному или остатку? И исходя из чего?

    3. Написал такую процедурку, и не могу решить, оставить последний neg или убрать? Как правильней, подскажите.


    Код (Text):
    1. SignedDivision proc uses ebx    ;на входе edx/eax - делимое (в пределах дворда), ecx - делитель
    2.                             ;на выходе eax - частное, edx - остаток, флаг C - деление на 0
    3.     mov ebx,1
    4.     test ecx,ecx
    5.     jz @ZeroDiv
    6.     jns @F
    7.         neg ebx
    8.         neg ecx
    9.     @@:
    10.     test eax,eax
    11.     jns @F
    12.         neg ebx
    13.         neg eax
    14.     @@:
    15.     div ecx
    16.     test ebx,ebx
    17.     jns @F
    18.         neg eax
    19.         ;neg edx
    20.     @@:
    21.     clc
    22.     ret
    23. @ZeroDiv:
    24.     stc
    25.     ret
    26.    
    27. SignedDivision endp




    В отличие от idiv, процедура выдаёт одинаковый результат для 7/(-5) и для (-7)/5. Как в частном так и в остатке. Тот же idiv ведёт себя по разному, и взять его за образец невозможно. Так нужен neg edx или нет? Имеет ли смысл знак применительно к остатку?
     
  2. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    А вообще, вопрос интересный.

    Посмотри во 2м томе команды FPU FPREM и FPREM1 - они обе вычисляют остаток, только он тоже разный :).
     
  3. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Вот чтобы уйти от неоднозначности и написал процедуру. А в какую сторону повернуть однозначность?



    Имхо, более логичным мне кажется без neg edx, т.е. остаток не может быть со знаком. С другой стороны, лезут сомнения, не позволяющие поставить точку: может чего упустил из виду, какие-нибудь подводные камни?
     
  4. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Я про мануал к чему говорил.

    Там есть такая формула:



    Даны числа A и B



    Остаток (A / B) = A - (Q * B)



    Где Q = Округление (A / B)



    Так вот, уже от того, как округляется (A / B) зависит значение Остатка.

    Поэтому и есть 2 команды - результат их различен.
     
  5. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    К сожалению, я не знаю, о каком мануале идёт речь :dntknw: А формулы эти вообще выдают 4 варианта остатка (в зависимости от способа округления и знаков входных данных).

    А=7, В=-5

    Q=-1 либо Q=-2

    Остаток = 2 либо -3



    А=-7, В=5

    Q=-1 либо Q=-2

    Остаток = -2 либо 3



    Я же как раз хочу уйти от этой неоднозначности, делаю, что остаток всегда 2 (согласно логике). Только никак не решу, должен ли знак частного распространяться на остаток, или нет.
     
  6. Julius

    Julius New Member

    Публикаций:
    0
    Регистрация:
    31 окт 2003
    Сообщения:
    42
    Вот и у меня засело в башке и не даёт покоя такой вопрос, вернее несколько:

    1. Для idiv 7/(-5) <> (-7)/5. Как с этим быть?


    А чем тебя не устраивает работа idiv.

    Работает она правильно, как и ожидают все нормальные люди.

    Вот делишь ты 7/(-5) и получаешь частное -1 и оснаток 2

    (так как 7 - число положительное, то естественно и остаток положителен)

    А если делишь (-7)/5, то получаешь частное -1 и остаток -2

    (так как -7 - число отрицательное, то естественно и остаток отрицателен)

    Не надо путать остаток от знакового деления и модуль остатка от знакового деления, это разные вещи.
     
  7. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Julius







    Это говорит о том, что ты даже и не пробовал. А когда попробуешь, то возможно и заметишь, что остаток вовсе и не -2, а очень даже 4 :)



    xor edx,edx

    mov eax,-7

    mov ecx,5

    idiv ecx

    PrintDec edx

    и нарисуется edx = 4.



    Вот этим и не устраивает меня idiv. 4 вообще как пришить к этому делу???



    P.S. за ненормального спасибо :dntknw:
     
  8. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    cresta

    обнулять edx(dx или ah) нужно для div

    а для idiv существуют cdq, cwd и cbw
     
  9. Julius

    Julius New Member

    Публикаций:
    0
    Регистрация:
    31 окт 2003
    Сообщения:
    42
    Это говорит о том, что ты даже и не пробовал. А когда попробуешь, то возможно и заметишь, что остаток вовсе и не -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 битное знаковое число. Расширение знаком еще никто не отменял.

    за ненормального спасибо :dntknw:

    Без абид, это просто такой словестный оборот.
     
  10. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    cresta



    Julius и Black_mirror правы на 100%.

    Стоит заглянуть в IA-32, чтобы убедиться в том что:

    1) Делимое в IDIV всегда содержится в (E)DX:dntknw:E)AX. Если ты кидаешь свое число в EAX, то EDX должно быть знаковым расширением EAX, т.е. 0 при EAX >= 0 и -1 при EAX < 0. Инструкции CWD и CDQ именно для этого и предназначены - они заполняют (E)DX знаковым битом (E)AX.

    2) Знак остатка всегда равен знаку делимого а "округление" результата, о котором говорил S_Т_A_S_, всегда осуществляется в сторону 0, т.е. произведение частного на делитель по модулю всегда меньше делимого. Именно поэтому остаток и называется "остатком", а не избытком или еще чем.
    Код (Text):
    1. 7/(-5) = (5+2)/(-5) = -1 + 2/(-5) = -1 и +2 в остатке
    2. (-7)/5 = (-5-2)/5   = -1 + (-2)/5 = -1 и -2 в остатке
    т.е. остатки имеют разные знаки, но с учетом знака делителя результат получается один и тотже "минус одна целая и две пятых".
     
  11. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Black_mirror, Julius



    Спасибо за подсказки. Значит велосипед изобретаю :)
     
  12. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    leo



    Вот это похоже, самое главное.

    А то, что знак остатка всегда равен знаку делимого, как мне кажется только усложняет жизнь. Если например, я хочу работать с остатком как с беззнаковым, то вынужден проверять его (либо частное) на знак. И соответственно корректировать. Согласен, для машины может в каких-то (или во всех) случаях логично, что остаток может иметь знак, но программу то пишет не машина...



    Если такая абстрактная задача: поделить кучу чисел и суммировать остатки, то для 7/-5 и -7/5 в итоге окажется, что никакого остатка и нет вовсе. Что на мой взгляд неправильно. Да собственно та процедура, что описана в вопросе, это попытка уйти от машинной логики к логике человеческой.
     
  13. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    cresta

    > "уйти от машинной логики к логике человеческой"

    Знаковый остаток - это как раз не машинная, а человеческая логика, реализованная в машине.

    Вспомним Лису Алису из детского фильма: -7 на 5 не делится ? не делится, тогда возьмем ближайшее меньшее (по модулю), которое делится, это -5. Получим результат = -1.

    А остаток это есть разница между тем что требовалось разделить (-7) и тем "меньшим" что мы взяли (-5), т.е. -2. Вся ясно, логично и однозначно.

    Резюме: знаковый остаток - это не прихоти "машины", а правила математики. Если в какой-то задаче нужно брать модуль остатка, то тут ничего не поделаешь, придется проверять знак и корректировать, если нужно.
     
  14. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    leo >




    Вот как раз не всегда :derisive:

    ТОт остаток, о котором говорилось не соответствеут стандарту IEEE 754.



    В книгах двойных слов (IA-32 Intel® Architecture Software Developer’s Manual Volume 2A: Instruction Set Reference) рассказано о такой инструкции:



    FPREM1—Partial Remainder



     
  15. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    leo



    ЧТО???



    Остаток от деления отрицателен? Садись, Вовочка, двойка!
     
  16. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Эй, Вы, гуру!!!



    Ну посоветуйте что-нибудь в конце-то концов! А то я уже запутался окончательно и бесповоротно :dntknw:((



    Кого слушать-то???
     
  17. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Теорема. Для данного целого отличного от нуля числа b, всякое целое число а единственным образом представимо в виде а = bq + r , где 0 <= r < |b|.





    Определение. Число q называется неполным частным, а число r — остатком от деления а на b .





    Заметим, дорогие читатели, что остаток — всегда есть число неотрицательное, а вот неполное частное может быть каким угодно целым числом. Поэтому на вопрос: “Сколько будет минус пять поделить на три с остатком?”, каждый должен бойко отвечать: “Минус два, в остатке — один!”. Но за добрый десяток лет опыта приема устных вступительных экзаменов в университет, судьба еще не послала мне абитуриента, правильно ответившего на этот вопрос. А ведь это дети, специально готовившие себя поступать именно на математико-механический факультет. “Печально я гляжу на наше поколение...”



    ЛЮБОМУ, кто скажет тебе, что остаток - число отрицательное - плюнь в лицо.
     
  18. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    -7 mod 5 = 3 (!!!)

    5 mod (-7) = 5
     
  19. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Да уж... Час от часу не легче. Теперь -5/3 = -2 и в остатке один.... А -7/5 значит должно быть -2(частное) и 3 (остаток).



    Всё это напоминает анекдот про того еврея, ответившего на вопрос "Сколько будет дважды два?" естественно вопросом: "А сколько Вам надо?"



    Итого имеем уже семь разных вариантов
     
  20. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Еще раз - если мы говорим об остатке от целочисленного деления тут двух мнений быть не может. Одно мое, другое неправильное :) А правила теории чисел не мной и не вчера выдуманы.