Главная страница


ru.algorithms

 
 - RU.ALGORITHMS ----------------------------------------------------------------
 From : Sashka Yackubtchick                  2:5054/29.54   01 Dec 2001  04:49:04
 To : All
 Subject : Алгоритм Ферма нахождения делителей
 -------------------------------------------------------------------------------- 
 
 
 Черновой вариант сабжа.
 Мысли, код, мнения как всегда мною приветсвуются
 и внимательно изучаются.
 
 === Cut ===
 .586
 .model flat,stdcall
 option casemap:none
 include C:\masm32\include\windows.inc
 include C:\masm32\include\kernel32.inc
 include C:\masm32\include\user32.inc
 includelib kernel32.lib
 includelib user32.lib
 FermaAlgo proto :DWORD
 .code
 start:
 
  invoke FermaAlgo,127*139
  call ExitProcess
 ;Алгоритм Ферма по нахождению близко расположеных делителей числа:
 ;Ввод: Hечётное натуральное число.
 ;Вывод: Множетели числа N или сообщение о том, что N простое.
 ;Шаг1: Положить x = [sqrt(n)], если x^2 = n, то x является делителем числа n
 ;и работа алгоритма останавливается. В противном случае увеличить X на 1
 ;и перейти к шагу 2
 ;Шаг2: Если x = (n+1)/2, то число n простое, и работа алгоритма
 ;останавливается;
 ;в противном случае вычислить y = sqrt(x^2 - n)
 ;Шаг3: Если число y целое (т.е. [y]^2 = x^2 - n), то n раскладывается в
 ;произведение
 ;(x+y)(x-y), и работа алгоритма останавливается; в противном случае перейти к
 ;шагу 2
 FermaAlgo proc num
 LOCAL sqrt:DWORD
 ;Стадия 1: Проверка корректности ввода.
 ;Проверим сразу случаи 0,1 а "заодно" и 2,3
  cmp num,4
  mov eax,num
  jnc @F
  jmp [eax*4][offset jmptbl] ;на обработку случаев 1,2,3,0
 @@: test eax,1
  je @even
 ;Стадия 2 - инициализация переменных и проверка на полный квадрат
 ;Шаг2 сравнивает число Х с одной и той же величиной (n+1)/2
 ;расчитать её нужно перед началом цикла и положить в неизменяемый регистр
 ;edi = (n+1)/2
 ;x всегда изменяется на 1 и так же может применятся при вычислении "соседнего"
 квадрата
 ;дадим ему также "персональный" регистр
 ;esi = x
 ;и X^2-n поскольку X^2 увеличивается равномерно а n постоянна то для скорости
 ;ecx = X^2 - n
 ;разница между (X^2-n) и (X+1)^2 - n составляет разницу между X^2 и (X+1)^2 а
 эта разница
 ;равна 2X +1 поскольку (X+1)^2 = X^2+2X+1
 ;Вычислим начальное значение X = sqrt(n)
 .data?
 cr dw ?
 .code
  fstcw cr
  or cr,0000010000000000b ;Округляем в меньшую сторону.
  fldcw cr
  fild num
  fsqrt
  fistp sqrt
  mov esi,sqrt ;инициализируем X
  mov eax,sqrt ;X -> eax
  mul eax       ;eax ^ 2
  cmp eax,num ;полный квадрат?
  je @fullsq
  mov edi,num
  lea ecx,[eax][esi*2][1] ;ecx = (X+1)^2
  sub ecx,edi  ;ecx = (X+1)^2 - n
  inc edi
  shr edi,1   ;edi = (n+1)/2
  mov sqrt,esi
  jmp init
 @again:
  mov sqrt,ecx
  fild sqrt
  fsqrt
  fistp sqrt  ;sqrt = sqrt(x^2-n)
  mov eax,sqrt
  lea edx,[ecx][eax]   ;проверка на расхождение чётности\нечётности
  test edx,1 ;числа и корня если сумма нечётная то корень явно не целый
  jne @odd ;
  mul eax  ;тем не менее ~ 50% нецелых корней "пройдёт" этот тест
  cmp eax,ecx ;для этих случаев дополнительная проверка.
  je @found
 @odd:
  lea ecx,[ecx][esi*2][1]
 
 init:
  inc esi
  cmp esi,edi
 
  jne @again
 .data
 jmptbl dd @case0,@case1,@Prime,@Prime
 MsgPrime db 'Это простое число - ',13,10
  db 'Оно делится только на единицу и на себя',0
 TtlMsgPrime db "Простое число",0
 .code
 @Prime:
  invoke MessageBox,0,offset MsgPrime,offset TtlMsgPrime,0
  ret
 @case0:
 .data
 MsgZero  db 'Число = 0. Делить его бесмыслено',0
 .code
  invoke MessageBox,0,offset MsgZero,0,0
  ret
 @case1:
 .data
 Msg1 db "Число = 1. Единица делится только сама на себя",0
 .code
  invoke MessageBox,0,offset Msg1,0,0
  ret
 @even:
 .data
 MsgEven db "Число чётное",0
 .code
  invoke MessageBox,0,offset MsgEven,0,0
  ret
 @fullsq:
  mov eax,esi
  mov edx,esi
  jmp @out
 @found:
  mov eax,esi ;eax = X
  mov edx,sqrt ;edx = Y
  sub eax,edx ;a = X-Y
  lea edx,[esi][edx] ;b = X+Y
 @out:
 .data
 tmpl  db 'Множители числа %i',13,10
  db '%i,%i',13,10
  db 13,10,0
 MsgFound  db 'Число разложено на множетели',0
 .data?
 buffer db 64 dup (?)
 .code
  invoke wsprintf,offset buffer,offset tmpl,num,eax,edx
  invoke MessageBox,0,offset buffer,offset MsgFound,0
  ret
 
 FermaAlgo endp
  ret
  end start
 === Cut ===
 
 Пока!
              Sashka, The Svin.
 
 --- GoldED/W32 3.00.Beta1+
  * Origin: Svin, Perm, Russia  (2:5054/29.54)
 
 

Вернуться к списку тем, сортированных по: возрастание даты  уменьшение даты  тема  автор 

 Тема:    Автор:    Дата:  
 Алгоритм Ферма нахождения делителей   Sashka Yackubtchick   01 Dec 2001 04:49:04 
Архивное /ru.algorithms/33843c085334.html, оценка 2 из 5, голосов 10
Яндекс.Метрика
Valid HTML 4.01 Transitional