Большие числа

Тема в разделе "WASM.ASSEMBLER", создана пользователем Crash, 16 ноя 2006.

  1. Crash

    Crash New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2004
    Сообщения:
    73
    Привет всем!

    Допустим, пользователь вводит в программу с клавиатуры
    пятиричное представление числа, имеющее до 12 знаков
    перед десятичной точкой и до 4 знаков дробной части.
    Число всегда положительное.

    Программа должна уметь складывать и умножать два таких введенных числа,
    не используя MUL, IMUL и команды процессора плавающей точки.

    Как можно хранить такое число в памяти?
    И как можно умножать два таких числа, используя операции сложения и сдвига?
     
  2. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Crash
    В какой бы системе счисления ни было введено число, его всегда можно преобразовать в другую, для которой тебе будет известно как складывать, умножать и делить.

    В чем конкретно проблема?
    Не умеешь преобразовывать строку в число (и обратно для вывода результата)? Не умеешь выполнять арифметические операции над числами?
    Тебе нужно готовое решение?
     
  3. gilg

    gilg New Member

    Публикаций:
    0
    Регистрация:
    19 май 2005
    Сообщения:
    527
    Зубков "Ассемблер для DOS, Windows и UNIX" - с готовыми алгоритмами
     
  4. Crash

    Crash New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2004
    Сообщения:
    73
    Мне нужно каким-то образом хранить числа из 48 бит в памяти. И уметь складывать и умножать их. Преобразовывать из строки в число и обратно я знаю, как.
     
  5. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Crash
    Подозреваю, тебе сюда.
     
  6. Miller Rabin

    Miller Rabin New Member

    Публикаций:
    0
    Регистрация:
    4 янв 2006
    Сообщения:
    185
    Crash
    На четвертом курсе у универе перед тем как давать реализацию криптосистем нам давали задание
    реализовать сложение, вычитание, умножение, деление и нахождение остатка чисел любой разрядности
    Я полагаю у тебя что-то похожее
    Когда я делал свою реализацию я использовал
    двоичный формат big endian - младший байт самый левый

    Чтобы было проще можешь вводить числа как строку в шестнадатеричной системе счисления
    типа:
    198756ACD76593B

    Такое число легко сконвертировать в двоичную форму
    берешь последовательно символы строки с конца
    и смотришь если цифра, то отнимаешь 48
    если буква, то отнимаешь 55 ;Хотя наверное можно и лучше придумать
    Результат в Al
    Берешь втрой байт сконца
    Делаешь тоже самое
    результат в ah
    Сохраняешь получившийся байт в нужном месте в зависимости от выбранной спецификации Big Endian или Little Endian
    и так пока не дойдешь до начала строки
    ВСЕ

    Когда это сделаешь то складывать и вычитать такие числа можно с помощью замечательных команд
    adc и sbb

    Умножать числа можно как стобиком команда mul для этого замечательно подходит
    А вот хорошие алгоримы деления и нахождение остатка довольно сложные
    тебе лучше поискать статью в инете
    Такую информацию легко найти если искать, например, реализацию RSA
     
  7. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Crash
    Значит, имеем числа с фиксированной запятой: 12,4

    Такие числа можно легко преобразовать в целые, умножением на 10000. Само умножение делать не надо, просто при конвертировании нужно "забыть" про запятую и добавить нужное кол-во нулей справа, если дробных знаков окажется меньше 4х.

    Результат прекрасно умещается в 64 бит. Далее можно складывать через add + adc и вычитать sub + sbb. Умножать и делить труднее, как уже заметил Miller Rabin, но тоже можно.

    Результат нужно будет разделить на 10000, т.е. сдвинуть запятую на 4 знака.

    Miller Rabin
    Да, по нику можно догадаться, что Вы увлекаетесь криптографией :)
     
  8. lukash

    lukash New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2006
    Сообщения:
    142
    Не знаю, поможет ли это кому, но на информатике такие числа мы раскладывали по следующему алгоритму:

    Допустим, есть большое число

    Код (Text):
    1. 30!= 265252859812191058636308480000000
    Можно записать, как

    Код (Text):
    1. 30!=2*(10^4)^8+6525*(10^4)^7+2859 *(10^4)^6+8121 *(10^4)^5+
    2. +9105 *(10^4)^4+8636 *(10^4)^3+3084 *(10^4)^2+8000*(10^4)^1+
    3. +0000 *(10^4)^0
    (если брать основу в 1000).

    В таком виде его можно записать в таблицу

    Код (Text):
    1. A[0]    A[1]    A[2]    A[3]        CH
    2. 0   0   0   0          
    3. 1   2   0   0       2
    4. 1   26  0   0       6
    5. 1   265 0   0       5
    6. 1   2652    0   0       2
    7. 2   6525    2   0       5
    8. 2   5252    26  0       2
    9. 2   2528    265 0       8
    10. ……………………………………….
    Вот и сам код для чтения числа в таблицу и его восстановление из нее

    Код (Text):
    1. Const maxDig=1000;
    2.       osn=10;
    3. Type tlong=array[0..MaxDig] of integer;
    4.  
    5. Var f:text;
    6.     A,B:tlong;
    7.     i,k: integer;
    8. Procedure Writelong;
    9.   Var i:integer;
    10.       l: string;
    11.   begin
    12.     Write(f,A[k]);
    13.     If k>1
    14.       then
    15.         begin
    16.           While k-1>=1 do
    17.             begin
    18.               str(A[k-1],l);
    19.               Write(f,l);
    20.               k:=k-1;
    21.             end;
    22.         end;
    23.   end;
    24. Procedure Readlong;
    25.   Var ch:char;
    26.       i,l,j,zn: integer;
    27.   begin
    28.     zn:=0;
    29.     A[0]:=1;
    30.     Read(f,ch);
    31.     val(ch,A[1],j);
    32.     zn:=1;
    33.     While (not eof(f)) do
    34.       begin
    35.         REad(f,ch);
    36.         Val(ch,l,j);
    37.         A[1]:=a[1]*10+l;
    38.         zn:=zn+1;
    39.         For i:=1 to a[0] do
    40.           begin
    41.             If (i=a[0]) and(A[i]>=osn)
    42.               then
    43.                 begin
    44.                   a[0]:=a[0]+1;
    45.                   zn:=0;
    46.                 end;
    47.             If A[i]>=osn
    48.               then
    49.                 begin
    50.                   A[i+1]:=a[i+1]*10+a[i] div osn;
    51.                   a[i]:=a[i]mod osn;
    52.                 end;
    53.           end;
    54.       end;
    55.     end;
    56.   begin
    57.     k:=0;
    58.     Assign(f,'Task.dat');
    59.     Reset(f);
    60.     Readlong;
    61.     Close(f);
    62.     Assign(f,'Result.sol');
    63.     Rewrite(f);
    64.     k:=A[0];
    65.     Writelong;
    66.     Close(f);
    67.   end.
    68.  
    69. А вот процедура для сложения таких больших чисел
    70.  
    71. Procedure Suma (a,b: tlong; Var c: tlong);
    72.   Var i: integer;
    73.     begin
    74.       If a[0]>b[0]
    75.         then c[0]:=a[0]
    76.         else c[0]:=b[0];
    77.       For i:=1 to c[0] do
    78.         begin
    79.           c[i]:=(a[i]+b[i]+c[i]) mod osn;
    80.           c[i+1]:=(a[i]+b[i]+c[i]) div 1000;
    81.         end;
    82.       If c[c[0+1]]<>0
    83.         then c[0]:=c[0]+1;
    84.     end;
    По-моему, этот код не корректно работает с нулями. Когда-то эту ошибку исправил, но сейчас лень разбираться:)