Деление в двоично-десятичной системе

Тема в разделе "WASM.ASSEMBLER", создана пользователем GMSD, 15 ноя 2008.

  1. GMSD

    GMSD New Member

    Публикаций:
    0
    Регистрация:
    15 ноя 2008
    Сообщения:
    7
    Задача следующая. Необходимо реализовать (можно просто ввиде алгоритма, или просто суть метода) деление двух двухбайтовых чисел друг на друга без остатка, используя только операцию сложение. Исходные числа двоично-десятичные. Кто знает как это реализовать подскажите, пожалуста, а то уже всю голову сломал!
     
  2. meduza

    meduza New Member

    Публикаций:
    0
    Регистрация:
    15 авг 2008
    Сообщения:
    212
    GMSD
    в Зубкове есть
     
  3. GMSD

    GMSD New Member

    Публикаций:
    0
    Регистрация:
    15 ноя 2008
    Сообщения:
    7
    meduza
    Полность название можешь написать?
     
  4. meduza

    meduza New Member

    Публикаций:
    0
    Регистрация:
    15 авг 2008
    Сообщения:
    212
    GMSD
    Зубков С.В. "Ассемблер для DOS, Windows, Unix" ISBN 5-94074-003-0
    Также есть в Юров В. "Ассемблер", да и вообще в любом нормальном учебнике по ассемблеру x86.
     
  5. dag

    dag New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2004
    Сообщения:
    446
    Код (Text):
    1.   слово делимое = ?;
    2.   слово делитель = ?;
    3.   слово накопитель = 0;
    4.   слово частное = 0;
    5.   слово знак = 1;
    6.   слово знакостатка = 1;
    7.   слово остаток = 0;
    8.   если (делимое<0)
    9.   {
    10.      знак = -знак;
    11.      знакостатка = -знакостатка;
    12.      делимое = -делимое;
    13.   }
    14.   если (делитель<0)
    15.   {
    16.      знак = -знак;
    17.      делитель = -делитель;
    18.   }
    19.   если (делитель != 0)
    20.   {
    21.      пока (накопитель<делимое)
    22.      {
    23.         накопитель+=делитель;
    24.         частное++;
    25.      }
    26.      остаток = делимое - накопитель;
    27.      если (знак < 0)
    28.      {
    29.        частное=-частное;
    30.      }
    31.      если (знакостатка < 0)
    32.      {
    33.         остаток = -остаток;
    34.      }
    35.   }
    36.   иначе
    37.   {
    38.      // деление на ноль
    39.   }
    http://ru.wikipedia.org/wiki/Деление_(математика)
    http://www.intuit.ru/department/se/pbmsu/2/
     
  6. GMSD

    GMSD New Member

    Публикаций:
    0
    Регистрация:
    15 ноя 2008
    Сообщения:
    7
    meduza
    Спасибо!
     
  7. GMSD

    GMSD New Member

    Публикаций:
    0
    Регистрация:
    15 ноя 2008
    Сообщения:
    7
    meduza
    Нашел в этих книга "арифметические действия над упакованными BCDчислами", сложение, вычитание, умножение и деление. Везде деление рассматривается с помощью div.
    Мне надо деление реализовать сложением. Я слышал, что деление можно реализовать вычитанием, а вычитание - сложением с инверсией. Но хотелось бы поконкретнее, ведь действия производятся с двоично-десятичными числами, коррекцию наверное делать надо еще???
     
  8. meduza

    meduza New Member

    Публикаций:
    0
    Регистрация:
    15 авг 2008
    Сообщения:
    212
    коррекция умножения (aam) и деления (aad) только с неупакованными BCD-числами работают. Команд "dam" и "dad" нет. Ты с упакованными работаешь?

    я не знаю как это реализовать, но на твоем месте на бумаге бы продумал весь алгоритм. Можно попробовать "столбиком" делить, как люди.
     
  9. GMSD

    GMSD New Member

    Публикаций:
    0
    Регистрация:
    15 ноя 2008
    Сообщения:
    7
    С упакованными.
    meduza
    Спасиб за совет.
     
  10. meduza

    meduza New Member

    Публикаций:
    0
    Регистрация:
    15 авг 2008
    Сообщения:
    212
    суть в том, что из делимого надо в цикле вычитать делитель до тех пор, пока делимое не станет меньше делителя, причем на каждой итерации к частному прибавлять еденицу (изначально оно равно 0).

    Ну а вычитание через сложение просто: a - b = a + (-b)
     
  11. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.787
    По определению умножение -- это многократное сложение одного и того же числа, соответственно, деление -- это многократное вычитание одного и того же числа из делимого.
    алгоритм деления без восстановления Из делимого вычитается делитель, умноженный на степень двойки. Произведение числа на 2ⁿ эквивалентно сдвигу этого числа на n разрядов влево. (процессор i8080/Кр580ВМ80 сдвиги поддерживал) Это позволит нам делить за фиксированное количество операций. Деление на байт - 8 операций, деление на слово - 16 операций и т.д. Если знак результата положительный, то нужно прибавить 2ⁿ к частному, если знак результата отрицательный — частное не увеличивается. Когда знак результата меняется на отрицательный, вычитание заменяется сложением. Так повторяется при уменьшающихся степенях двойки до тех пор, пока не будет достигнута степень равная нулю. Остатком считается последний положительный результат. Разделим 125 на 11. Делитель укладывается в байт (11<255) поэтому начинаем с 2**7. В начале вычисления частное всегда равно 0:
    125 – 11 * 2**7 = –1283
    –1283 +11 * 2**6 = –579
    –579 +11 * 2**5 = –227
    –227 +11 * 2**4 = –51
    –51 + 11 * 2³ = 37 ;результат положительный, поэтому складываем 2³ с частным, частное равно 8+0=8
    37 – 11 * 2² = – 7
    –7 + 11 * 2¹ = 15 ;результат положительный, поэтому складываем 2¹ с частным, частное равно 8+2=10
    15 –11 * 2º = 4 ;результат положительный, поэтому складываем 2º с частным, частное равно 10+1=11, остаток равен 4
     
  12. GMSD

    GMSD New Member

    Публикаций:
    0
    Регистрация:
    15 ноя 2008
    Сообщения:
    7
    Я сделал подругому
    вычитание заменил сложением по следующей формуле

    разность=инверсия(инверсия(уменьшаемое)+вычитаемое)

    после каждого сложения - двоично-десятичная коррекция.
    "Складываем" пока числитель больше знаменателя.
     
  13. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.787
    GMSD
    Оригинально!
    -A=NOT(A)+1
    -A-1=NOT(A)
    NOT(NOT(A)+B)=NOT(-A-1+B)=A+1-B-1=A-B
    Сам нашел или прочитал? Если, прочитал, тогда, пожалуйста, укажи источник
    А вот по эффективности и времени исполнения, допустим, делим 126 на 3 -- если вычитанием, до тех пор, пока разница не станет меньше 3 -- это займет 42 шага, а если через алгоритм деления без восстановления с использованием сложения, вычитания и сдвигов -- то всего за 8 шагов
     
  14. GMSD

    GMSD New Member

    Публикаций:
    0
    Регистрация:
    15 ноя 2008
    Сообщения:
    7
    Mikl___
    Слышал просто,что как-то через инверсию можно сделать, посидел и додумался.
    Мне это не для очень важного дела нужно было, так-что насчет времени и эффективности особо не парился :)
     
  15. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.787
    GMSD
    Для многократного вычитания, достаточно один раз сделать NOT(B)+1=-B сохранить значение -B, а затем делать A+(-B) что соостветствует A-B (всего одна операция) а по твоему методу (оригинальному, конечно) NOT(NOT(A)+B)) каждый раз при вычитании используется три! операции (две инверсии и одно сложение). Реальному делению должны предшествовать проверки, а не является делитель равным 0 (деление на ноль вызовет исключение), не является ли делитель равным 1 (тогда деление не имеет смысла -- ответ уже известен), не является ли делитель числом, кратным 2, тогда часть деления будет заменена на сдвиги вправо на число равное степени двойки, не больше ли делитель делимого, тогда при целочисленом делении частное будет равно нулю, либо предварительно требуется умножить делимое на поправочный коэффициент и т.д.