日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

整数n分解成素数乘积c语言,用C语言和汇编语言实现将1个整数分解成几个素数的乘积...

發布時間:2023/12/8 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 整数n分解成素数乘积c语言,用C语言和汇编语言实现将1个整数分解成几个素数的乘积... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

任何1個大于2的整數都可以分解成幾個素數的乘積。將1個整數分解成幾個素數的乘積是個熱門話題。

經常有人問到。本文試圖用C語言和32位X86匯編語言給出一個比較好的實現。希望對c語言學習者和

匯編語言學習者帶來幫助。

問題的提出:將一個整數分解素因數

根據算術基本定理,任何大于2的正整數都可以表示為素數的乘積,如果不考慮這些素數出現的次序,其

表示方式為唯一的。本題目的要求是輸入一個正整數,將這個正整數顯示為幾個素數乘積的形式,如

1=1

2=2

3=3

4=2*2

5=5

6=2*3

7=7

...

60=2*2*3*5

算法:

對于合數n,它總可表示為兩個數的乘積,如n=a*b,令a<=b,容易證明a <= sqrt(n),這里sqrt(n)表示n的

平方根,下同。這說明了,用i =2 到 sqrt(n)之間的數逐一試除,如果所有的i都不是n的因數,則n一定

是一個素數。如果在試除過程中,某個i能夠整數n,則將i存入因子表,n/i => n,直到 i*i大于n為止。

在試除過程中,若p和q都是n的因子,p是素數,q大于p,q是p的倍數,如果p能夠整除n,則n = n / p,

這樣,最終n就不再是p的倍數,故n也不會是q的倍數,故在計算n = n / p這一過程,p一定是一個素數,

這種方法得到的所有因子都是素因子。

在所有的試除方法中,最少的試除步驟是用2到sqrt(n)之間的所有素數去試除。但這個算法需要預先算出

sqrt(n)之間的所有素數。這是最快的算法,但我們這里不打算搞得這么復雜,我們這里的算法是用2和所有2

以上的奇數去試出。因為如果一個數是4,6,8的倍數,那么他一定是2的倍數,當被2除后,就不需要試再試

除4,6,8了。

下面給出一個C語言的實現

#include #include typedef unsigned long DWORD;

//函數decomp_integer對n分解素因數,分解后的素數存入facArr數組,并返回因子的個數

int decomp_integer( DWORD n, DWORD facArr[])

{

DWORD fac; //n的可能的一個因子

int count;

if (n<4) //4以內的數,不需要分解

{

facArr[0]=n; return 1;

}

count=0;

//下面的while循環為2試出n,直到2不是n的因子為止

while ( (n & 1)==0) // 這里判斷偶數用 (n &1)==0,這比(n % 2)==0更快

{

facArr[count++]=2; n/=2;

}

fac=3; //用3到sqrt(n)之間的奇數試除

while (fac*fac<=n) // fac*fac <= n

{

while (n % fac==0)

{

facArr[count++]=fac;

n /= fac;

}

fac+=2;

}

if (n==1)

return count;

facArr[count++]=n;

return count;

}

int main(int argc, char* argv[])

{

DWORD n,facArray[32];

int i,count;

printf("Please input unsigned integer:");

scanf("%u",&n);

count=decomp_integer(n,facArray);

printf("%u=%u",n,facArray[0]);

for (i=1;i

匯編語言可能是最麻煩的語言,在實踐中,除非必要,好少有人用匯編語言寫程序。這主要是因為

1.同樣的題目,用匯編語言編程需要的代碼量較大,費時費力

2.匯編語言的可讀性很差,日后維護的成本也大。

許多有經驗的工程師對匯編語言寫程序都很頭疼,對許多初學這說,更是一件難以完成的任務。

初學者常犯的錯誤是,一上來就有匯編寫程序,不管有沒有理清頭緒,這樣造成的結果就是,程序改

了又改,但總是不對,好容易改對了,但程序的風格很差,代碼冗長,邏輯混亂,可讀性很差。其實,

用任何語言寫成都需要設計,程序應該具有模塊化,條理清晰,風格一致。匯編語言是最接近機器的

語言,編寫匯編程序,非常有利用理解計算機的工作原理。

個人覺得,對于一個邏輯比較復雜的匯編程序的設計,不妨采用高級語言為原型,用高級語言編譯運

行通過了,說明你也就對這個題目理解了,然后,看看你的程序,哪里可以簡化,哪里可以重構使其

更優雅。最后可將你用高級語言寫的程序翻譯成匯編語言,這里的翻譯不是簡單的翻譯,匯編語言有

匯編語言的特點,他具有更大的靈活性,開發者應該總是用最適當的方式來實現它。

下面是這個題目的匯編版本,使用masm32編寫。關于輸入輸出部分,使用的幾個Windows API函數,

這里說明如下:

程序使用ReadFile從控制臺輸入數據,使用WriteConsole輸出運算結果到控制臺。字符串到數的轉化

子程序是自己寫的。見myAtoi。而數到字符串的轉化調用的則是Windows API函數wsprintf。此外,程

序還用到GetStdHandle和ExitProcess,感興趣的同學,可以查MSDN來得到更多的信息。

在C語言版,外循環的判斷語句"while (fac*fac<=n)"使用了乘法,而匯編語言班則使用了性能更好的lea

指令,見下

mov edx,s_fac

mov eax,fac

lea edx,[edx+eax*4+4] ; (fac+2)*(fac+2)=s_fac * 4*fac+4

mov s_fac,edx

add fac,2?????????? ?; fac +=2

其基本原理為,若s_fac是fac的平方,則在求(fac+2)^2時,使用了數學公式(fac+2)^2= fac^2 + 4*fac +4,

這里的^表示乘方,程序中,fac和s_fac分別表示當前因子和當前因子的平方,然后當前因子加2,同時需要

更新s_fac,在上面的代碼中,先計算(fac+2)^2,(fac+2)=fac^2 + 4*fac +4=s_fac+ 4*fac +4,然后計算fac+2.

lea指令支持*4,*8這樣的形式,故這里使用lea指令而沒有時候性能很慢的乘法指令。

下面給出匯編語言版的代碼,可借助c版的程序來理解匯編版,同時請體會匯編語言和c語言在處理邏輯方面的

的不同,特別是分支和循環語句。

; 如何編譯鏈接該程序

; 本程序需使用masm32來編譯,若你的masm32安裝在c盤,請設置如下環境變量

; set include=c:\masm32\include

; set lib=c:\masm32\lib

; set PATH=c:\masm32\bin;%PATH%

; 若本程序名為decomp.asm,則運行如下命令編譯和鏈接和運行

; ml /c /coff decomp.asm

; link /subsystem:console decomp.obj

; decomp.exe

.386

.model flat,stdcall ; 32 bit memory model

option casemap :none ; case sensitive

include windows.inc

include user32.inc

includelib user32.lib

include kernel32.inc

includelib kernel32.lib

.data

facTab dd 32 dup(?) ;number的所有素因子

facCount dd ? ;number的所有素因子的個數

number dd ? ;被分解的數

fac dd ? ;number的當前因子

s_fac dd ? ;number的平方

tLen dd ? ;臨時變量,僅在調用Windows API函數是用

hInput dd ? ;標準輸入設備句柄

hOutput dd ? ;標準輸出設備句柄

inBuffer db 32 dup(?) ;輸入緩沖區

outBuffer db 128 dup(?) ;輸出緩沖區

.const

szFmtIn db '%u',0

szFmtOut1 db 'Please input an unsigned integer:'

szFmtOut2 db '%u=%u',0

szFmtOut4 db '*%u',0

.code

;use global varible, don't pass any in parameter in stack

dcomp proc far uses esi

mov esi,number ;esi is copy of n

cmp esi,4

jae case_02

case_01:

mov facTab[0],eax

mov ecx,1

jmp this_exit

case_02:

xor ecx,ecx ;ecx: copy of count

jmp loop_02_cmp

loop_02:

mov facTab[ecx*4], 2

inc ecx ;count++

shr esi,1 ;esi is copy of n,n /=2

loop_02_cmp:

mov edx,esi

and edx, 1

jz loop_02 ; n % 2==0

mov fac,3

mov s_fac, 9

jmp loop03_outer_cmp

loop03_outer:

jmp loop03_inner_cmp

loop03_inner:

mov edx, fac

mov facTab[ecx*4],edx ;fac[count++]=fac

inc ecx ;count++

xor edx,edx

mov eax,esi

div fac

mov esi,eax

loop03_inner_cmp:

xor edx,edx

mov eax,esi

div fac

or edx,edx

jz loop03_inner

mov edx,s_fac

mov eax,fac

lea edx,[edx+eax*4+4] ; (fac+2)*(fac+2)=s_fac * 4*fac+4

mov s_fac,edx

add fac,2 ; fac +=2

loop03_outer_cmp:

mov eax,s_fac

cmp eax,esi

jbe loop03_outer

cmp esi,1 ;

jz this_exit ; n ==1

mov facTab[ecx*4],esi

inc ecx

mov eax,ecx

this_exit:

mov eax,ecx ;返回素因子數

ret

dcomp endp

; convert from a string to a integer

myAtoi proc far C uses ebx esi, var_String

mov esi,var_String ;in parameter => esi

mov ebx,10

xor eax,eax

xor ecx,ecx

loop_read_char:

mov cl,byte ptr [esi] ; get a char from in_buff

inc esi

sub cl,'0'

cmp cl,9

ja input_exit ;if the char '9', then jump out loop

mul ebx

add eax,ecx

jmp loop_read_char

input_exit:

ret

myAtoi endp

; use global varible, don't pass parameter in stack

; number: in parameter

; facTab: in paramter

; facCount: factor count

; hInstance: input device handle

output_fac proc far C uses ebx edi

lea edi, outBuffer

mov eax,facTab[0]

invoke wsprintf, edi, addr szFmtOut2,number,eax

add edi, eax

mov ebx,1

jmp next_cmp

convert_loop:

mov eax,facTab[ebx*4]

invoke wsprintf,edi,addr szFmtOut4,eax

add edi, eax ;edi the write pointer in next ; 下次輸出時的地址送edi

inc ebx

next_cmp:

cmp ebx,facCount

jb convert_loop

print:

lea eax, outBuffer

sub edi, eax ;計算輸出的字符串的長度,存入edi

invoke WriteConsole,hOutput,addr outBuffer,edi,addr tLen,0 ;在控制臺輸出

ret

output_fac endp

main proc far

invoke GetStdHandle,STD_OUTPUT_HANDLE ; 獲取控制臺輸出設備的句柄

mov hOutput,eax

invoke WriteConsole,hOutput,addr szFmtOut1,sizeof szFmtOut1,addr tLen,0

invoke GetStdHandle,STD_INPUT_HANDLE ; 獲取控制臺輸入設備的句柄

mov hInput, eax

invoke ReadFile,hInput,addr inBuffer,sizeof inBuffer,ADDR tLen,NULL

lea eax, inBuffer

invoke myAtoi,eax ;轉化字符串為一個數

mov number, eax ;將這個數存入number

invoke dcomp ;調用因子分解子程序,,各個因子存入facTab

mov facCount,eax ;分解后的因子個數存入facCount

invoke output_fac ;調用output_fac打印number的分解式

xor eax, eax

invoke ExitProcess,eax ;退出進程

ret

main endp

end main

liangbch@263.net, 轉載請注明出處。

總結

以上是生活随笔為你收集整理的整数n分解成素数乘积c语言,用C语言和汇编语言实现将1个整数分解成几个素数的乘积...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。