Задача следующая. Необходимо реализовать (можно просто ввиде алгоритма, или просто суть метода) деление двух двухбайтовых чисел друг на друга без остатка, используя только операцию сложение. Исходные числа двоично-десятичные. Кто знает как это реализовать подскажите, пожалуста, а то уже всю голову сломал!
GMSD Зубков С.В. "Ассемблер для DOS, Windows, Unix" ISBN 5-94074-003-0 Также есть в Юров В. "Ассемблер", да и вообще в любом нормальном учебнике по ассемблеру x86.
Код (Text): слово делимое = ?; слово делитель = ?; слово накопитель = 0; слово частное = 0; слово знак = 1; слово знакостатка = 1; слово остаток = 0; если (делимое<0) { знак = -знак; знакостатка = -знакостатка; делимое = -делимое; } если (делитель<0) { знак = -знак; делитель = -делитель; } если (делитель != 0) { пока (накопитель<делимое) { накопитель+=делитель; частное++; } остаток = делимое - накопитель; если (знак < 0) { частное=-частное; } если (знакостатка < 0) { остаток = -остаток; } } иначе { // деление на ноль } http://ru.wikipedia.org/wiki/Деление_(математика) http://www.intuit.ru/department/se/pbmsu/2/
meduza Нашел в этих книга "арифметические действия над упакованными BCDчислами", сложение, вычитание, умножение и деление. Везде деление рассматривается с помощью div. Мне надо деление реализовать сложением. Я слышал, что деление можно реализовать вычитанием, а вычитание - сложением с инверсией. Но хотелось бы поконкретнее, ведь действия производятся с двоично-десятичными числами, коррекцию наверное делать надо еще???
коррекция умножения (aam) и деления (aad) только с неупакованными BCD-числами работают. Команд "dam" и "dad" нет. Ты с упакованными работаешь? я не знаю как это реализовать, но на твоем месте на бумаге бы продумал весь алгоритм. Можно попробовать "столбиком" делить, как люди.
суть в том, что из делимого надо в цикле вычитать делитель до тех пор, пока делимое не станет меньше делителя, причем на каждой итерации к частному прибавлять еденицу (изначально оно равно 0). Ну а вычитание через сложение просто: a - b = a + (-b)
По определению умножение -- это многократное сложение одного и того же числа, соответственно, деление -- это многократное вычитание одного и того же числа из делимого. алгоритм деления без восстановления Из делимого вычитается делитель, умноженный на степень двойки. Произведение числа на 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
Я сделал подругому вычитание заменил сложением по следующей формуле разность=инверсия(инверсия(уменьшаемое)+вычитаемое) после каждого сложения - двоично-десятичная коррекция. "Складываем" пока числитель больше знаменателя.
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 шагов
Mikl___ Слышал просто,что как-то через инверсию можно сделать, посидел и додумался. Мне это не для очень важного дела нужно было, так-что насчет времени и эффективности особо не парился
GMSD Для многократного вычитания, достаточно один раз сделать NOT(B)+1=-B сохранить значение -B, а затем делать A+(-B) что соостветствует A-B (всего одна операция) а по твоему методу (оригинальному, конечно) NOT(NOT(A)+B)) каждый раз при вычитании используется три! операции (две инверсии и одно сложение). Реальному делению должны предшествовать проверки, а не является делитель равным 0 (деление на ноль вызовет исключение), не является ли делитель равным 1 (тогда деление не имеет смысла -- ответ уже известен), не является ли делитель числом, кратным 2, тогда часть деления будет заменена на сдвиги вправо на число равное степени двойки, не больше ли делитель делимого, тогда при целочисленом делении частное будет равно нулю, либо предварительно требуется умножить делимое на поправочный коэффициент и т.д.