The product of dividing an integer into several prime numbers using C and assembly languages

Source: Internet
Author: User
Tags string to number

Any integer greater than 2 can be decomposed into the product of several prime numbers. Splitting an integer into the product of several prime numbers is a hot topic.
Some people often ask. This article attempts to provide a better implementation using C language and 32-bit x86 assembly language. C language learners and
Compilation language learners help.

Question: decomposing an integer into a prime factor
According to the basic arithmetic theorem, any positive integer greater than 2 can be expressed as the product of prime numbers.
The representation is unique. The purpose of this question is to enter a positive integer in the form of a product of several prime numbers, as shown in
For example
1 = 1
2 = 2
3 = 3
4 = 2*2
5 = 5
6 = 2*3
7 = 7
...
60 = 2*2*3*5

Algorithm:
For the sum N, it can always be expressed as the product of two numbers, such as N = A * B, so that a <= B, it is easy to prove a <= SQRT (N ), here SQRT (n) indicates n's
Square root, the same below. This shows that the number between I = 2 to SQRT (n) is used for Division One by one. If all I is not a factor of N, N must
Is a prime number. If an I can be an integer N during the Trial Division, I will be saved to the factor table, N/I => N until I * I is greater than N.

In the process of division, if p and q are all N factors, P is a prime number, Q is greater than p, q is a multiple of P, if P can divide N, then n = N/P,
In this way, n is no longer a multiple of P, so n is not a multiple of Q. Therefore, in the process of calculating n = N/P, P must be a prime number,
All the factors obtained by this method are prime factors.

Among all the Trial Division methods, the minimum Trial Division step is to use all prime numbers between 2 and SQRT (n) for Trial Division. However, this algorithm needs to be calculated in advance.
All prime numbers between SQRT (n. This is the fastest algorithm, but we don't want to make it so complicated here. Our algorithm here uses 2 and all 2
Try out the odd numbers above. Because if a number is a multiple of 4, 6, and 8, it must be a multiple of 2. If it is divided by 2, you do not need to try again.
Except for and 8.

 

Below is a C language implementation

# Include <stdio. h> # include <stdlib. h> typedef unsigned long DWORD; // The decomp_integer function is used to describe the prime number of n. The prime number is stored in the facarr array, and the number of factors int decomp_integer (dword n, DWORD facarr []) {dword fac; // a possible factor of N int count; number within 4 If (n <4, {facarr [0] = N; return 1 ;}count = 0; // The while loop below is 2 to test the N, until 2 is not a factor of N while (N & 1) = 0) // here, the even number is determined by (N & 1) = 0, which is equal to (n % 2) = 0 faster {facarr [count ++] = 2; N/= 2;} FAC = 3; // use 3 to 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 <count; I ++) printf ("* % d ", facarray [I]); printf ("\ n"); Return 0 ;}

Assembly language may be the most troublesome language. In practice, unless necessary, few people write programs in assembly language. This is mainly because
1. For the same question, it takes a lot of time and effort to program in assembly language.
2. The compilation language is poorly readable and will be costly to maintain in the future.

Many experienced engineers have a headache in writing assembly language programs. For many beginners, this is an even more difficult task.
A common mistake for beginners is that there is a Compilation Program as soon as it comes up. Whether or not there is a clear clue, the result is program change.
But it is always incorrect, so it is easy to correct, but the program style is very poor, the code is lengthy, the logic is chaotic, and the readability is very poor. In fact,
Writing Chengdu in any language requires design. The program should be modular, organized, and consistent in style. Assembly languages are the closest to machines
Language, Compilation Program, very useful to understand the working principle of the computer.

I personally think that for the design of an assembly program with complicated logic, we may wish to use the advanced language as the prototype and compile and run it in the advanced language.
The answer passes, indicating that you have understood this question. Then, let's see where your program can be simplified, and where it can be reconstructed to make it
More elegant. Finally, you can translate programs written in advanced languages into assembly languages. The translation here is not a simple translation.
The feature of assembly language is more flexible. Developers should always implement it in the most appropriate way.

The following is the compilation version of this question, which is written using masm32. Some Windows API functions are used for the input and output sections,
The description is as follows:
The program uses readfile to input data from the console, and uses writeconsole to output the calculation result to the console. Conversion from string to number
Subprograms are self-written. See myatoi. The number of String Conversion calls Windows API function wsprintf. In addition
Getstdhandle and exitprocess are also used in sequence. If you are interested, you can check msdn to get more information.

In the C language version, the while (FAC * FAC <= N) clause uses multiplication, while the Assembly Language class uses Lea with better performance.
For instructions, see
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

The basic principle is that if s_fac is the square of the FAC, a mathematical formula (FAC + 2) is used for finding (FAC + 2) ^ 2) ^ 2 = FAC ^ 2 + 4 * FAC + 4,
Here ^ represents the multiplication side. In the program, FAC and s_fac represent the square of the current factor and the current factor respectively, and then the current factor is added with 2.
Update s_fac. In the above Code, calculate (FAC + 2) ^ 2, (FAC + 2) first) = FAC ^ 2 + 4 * FAC + 4 = s_fac + 4 * FAC + 4, and then calculate FAC + 2.
Lea commands support the format of ** 4, ** 8. Therefore, Lea commands are used here, but there is no time for multiplication commands with slow performance.

The assembly language version code is provided below. You can use the C version program to understand the assembly version. At the same time, please understand the processing logic of the assembly language and C language.
In particular, branch and loop statements.

; How to compile and link the program; this program requires masm32 for compilation. If your masm32 is installed on the C drive, set the following environment variables; set include = c: \ masm32 \ include; set Lib = c: \ masm32 \ Lib; Set Path = c: \ masm32 \ bin; % PATH %; if the program name is decomp. ASM, then run the following command to compile and link and run; ml/C/coff decomp. ASM; Link/subsystem: Console decomp. OBJ; decomp.exe. 386. model flat, stdcall; 32 bit memory modeloption Casemap: none; Case sensitiveinclude windows. incinclude user32.incincludelib user32.libinclude kernel32. Incincludelib kernel32.lib. Data factab dd 32 DUP (?); Faccount dd?; Number of all prime factors number dd?; Number of decomposed FAC dd?; Current factor of number s_fac dd?; Number square tlen dd?; Temporary variables. Is hinput dd used only when Windows API functions are called?; Is the standard input device handle houtput dd?; Standard output device handle inbuffer dB 32 DUP (?); Input buffer outbuffer dB 128 DUP (?); Output buffer. 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 stackdcomp 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/= 2loop_02_cmp: mov edX, ESI and EDX, 1 JZ loop_02; N % 2 = 0 mov FAC, 3 mov s_fac, 9 JMP loop03_outer_cmploop03_outer: JMP loop03_inner_cmp loop03_inner: 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, mov edX 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; returns the prime factor number retdcomp endp; Convert from a string to a integermyatoi 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 <'0' or> '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 handleoutput_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; the address next time the output is sent to EDI Inc ebxnext_cmp: cmp ebx, faccount JB convert_loopprint: Lea eax, outbuffer sub EDI, eax; Calculate the length of the output string, and store it in EDI invoke writeconsole, houtput, ADDR outbuffer, EDI, ADDR tlen, 0; output RET output_fac endpmain proc far invoke getstdhandle, role; get the handle mov houtput, eax invoke writeconsole, houtput, ADDR handle, sizeof szfmtout1, ADDR tlen, 0 invoke getstdhandle, std_input_handle; get the handle mov hinput, eax invoke readfile, hinput, ADDR inbuffer, sizeof inbuffer, ADDR tlen, null Lea eax, inbuffer invoke myatoi, eax; convert the string to a number mov number and eax. Store the number into number invoke dcomp. Call the factorization subprogram. Each factor is saved to factab mov faccount and eax; the number of decomposed factors is stored in faccount invoke output_fac; the decomposed XOR eax, eax invoke exitprocess, and eax of output_fac are called; the process RET main endpend main is exited

 

Liangbch@263.net, reprinted please indicate the source.
 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.