PDA

View Full Version : Thuat toan chia


tuan795
18-11-2005, 09:30 AM
Ai hiểu rỏ thuật toán chia (pic) như 16bit chia cho 8bit 16bit chia cho 16bit giơi thiệu cho tôi với.

falleaf
19-11-2005, 07:06 PM
#define bf_carry 3, 0
#define bf_zero 3, 2

#define same 1
#define wreg 0

#define stc bsf bf_carry
#define clc bcf bf_carry

;-[ Div ]--------------------------------------------------------------
; Call w/: Number in f_divhi:f_divlo, divisor in W.
; Returns: Quotient in f_divlo, remainder in f_divhi. W preserved.
; Carry set if error. Z if divide by zero, NZ if divide overflow.
; Notes: Works by left shifted subtraction.
; Size = 29, Speed(w/ call&ret) = 7 cycles if div by zero
; Speed = 94 minimum, 129 maximum cycles

Div;
addlw 0 ; w+=0 (to test for div by zero)
stc ; set carry in case of error
btfsc bf_zero ; if zero
return ; return (error C,Z)

call DivSkipHiShift
iDivRepeat = 8
while iDivRepeat

call DivCode

iDivRepeat--
endw

rlf f_divlo, same ; C << lo << C

; If the first subtract didn't underflow, and the carry was shifted
; into the quotient, then it will be shifted back off the end by this
; last RLF. This will automatically raise carry to indicate an error.
; The divide will be accurate to quotients of 9-bits, but past that
; the quotient and remainder will be bogus and carry will be set.

bcf bf_zero ; NZ (in case of overflow error)
return ; we are done!

DivCode
rlf f_divlo, same ; C << lo << C
rlf f_divhi, same ; C << hi << C
btfss bf_carry ; if Carry
goto DivSkipHiShift ;
subwf f_divhi, same ; hi-=w
stc ; ignore carry
return ; done
; endif
DivSkipHiShift
subwf f_divhi, same ; hi-=w
btfsc bf_carry ; if carry set
return ; done
addwf f_divhi, same ; hi+=w
clc ; clear carry
return ; done





Đây là thuật toán chia 16bit cho 8bit. Bạn tìm hiểu và phân tích thêm nhé, có lẽ mafd_47a sẽ giúp bạn phân tích source code này thêm.

Chúc vui.

Vigorous
23-03-2006, 04:39 PM
Thế còn những thuật toán khác như +,-,*,/ với 2 số 16 bit thì sao?
Anh có biết xin chỉ giáo dùm nhé!

pb1
23-03-2006, 11:06 PM
Bác mafd_47a đâu rồi, phân tích giúp thuật toán này đi, em cũng đang rất muốn biết

thank bác

falleaf
30-03-2006, 02:10 AM
các bạn có thể tham khảo tại www.piclist.com

Chúc vui

thancongbao
18-04-2006, 01:06 PM
thuật toán chi với số bit lớn hơn một từ của VXL em thường dùng phương pháp chia nhị phận thường.Bác cứ hình dung lại phép chia thông thường khi mình học lớp 1 ấy bác sẽ làm được.
sơ sơ như thế này:
lần lượt lấy số có trọng số cao nhất chi cho số chia sau đó hạ tiếp số có trọng số cao nhất còn lại xuống kết hợp với số dự để chia cho số chia.Cứ thế cho tới hết.Để em tìm lại code trước đây em viết bằng ASM cho 8051,néu còn em sẽ cho bác để tham khảo hê hê hê !!!

falleaf
12-05-2006, 12:15 AM
Có rất nhiều thuật toán chia được phân tích trên www.piclist.com, thuật toán của bạn chỉ là một trong số các thuật toán đó.

Việc phân tích thuật toán và viết các giải thích cho mọi người là điều rất cần thiết vì nó sẽ giúp chúng ta phát triển các thuật toán tối ưu hoá chương trình.

Ở đây mình muốn đưa ra luồng này, nhằm phân tích nó, các bạn có thể copy và thảo luận về các thuật toán cơ bản này, chạy thử, và chuẩn hoá lại...

Chúc vui.

anhquangngai
02-11-2006, 08:55 PM
#define bf_carry 3, 0
#define bf_zero 3, 2

#define same 1
#define wreg 0

#define stc bsf bf_carry
#define clc bcf bf_carry

;-[ Div ]--------------------------------------------------------------
; Call w/: Number in f_divhi:f_divlo, divisor in W.
; Returns: Quotient in f_divlo, remainder in f_divhi. W preserved.
; Carry set if error. Z if divide by zero, NZ if divide overflow.
; Notes: Works by left shifted subtraction.
; Size = 29, Speed(w/ call&ret) = 7 cycles if div by zero
; Speed = 94 minimum, 129 maximum cycles

Div;
addlw 0 ; w+=0 (to test for div by zero)
stc ; set carry in case of error
btfsc bf_zero ; if zero
return ; return (error C,Z)

call DivSkipHiShift
iDivRepeat = 8
while iDivRepeat

call DivCode

iDivRepeat--
endw

rlf f_divlo, same ; C << lo << C

; If the first subtract didn't underflow, and the carry was shifted
; into the quotient, then it will be shifted back off the end by this
; last RLF. This will automatically raise carry to indicate an error.
; The divide will be accurate to quotients of 9-bits, but past that
; the quotient and remainder will be bogus and carry will be set.

bcf bf_zero ; NZ (in case of overflow error)
return ; we are done!

DivCode
rlf f_divlo, same ; C << lo << C
rlf f_divhi, same ; C << hi << C
btfss bf_carry ; if Carry
goto DivSkipHiShift ;
subwf f_divhi, same ; hi-=w
stc ; ignore carry
return ; done
; endif
DivSkipHiShift
subwf f_divhi, same ; hi-=w
btfsc bf_carry ; if carry set
return ; done
addwf f_divhi, same ; hi+=w
clc ; clear carry
return ; done





Đây là thuật toán chia 16bit cho 8bit. Bạn tìm hiểu và phân tích thêm nhé, có lẽ mafd_47a sẽ giúp bạn phân tích source code này thêm.

Chúc vui.

vậy thì khi muốn chia thì làm như thế nào?
Anh có thể chỉ cụ thể hơn dc ko?

tdm
04-11-2006, 08:55 AM
Ai hiểu rỏ thuật toán chia (pic) như 16bit chia cho 8bit 16bit chia cho 16bit giơi thiệu cho tôi với.


http://www.piclist.com/techref/microchip/math/div/index.htm
http://www.piclist.com/techref/microchip/math/mul/index.htm

chumeodihia
05-11-2006, 10:16 PM
Đây là phép chia 8 bit cho 8 bit lấy về tham khảo nhe bạn 16 bit cũng tương tự như vậy thôi:


#include <p18F4431.inc>
org 0x000000
SO_CHIA EQU 0X81
SO_DU EQU 0X82
DIV EQU 0X83
SO_DICH EQU 0X84
LUU_TAM EQU 0X85
KQ_CHIA EQU 0X86
MAIN
MOVLW .15
MOVWF DIV
MOVLW .10
MOVWF SO_CHIA

CLRF KQ_CHIA
CLRF SO_DU
CLRF LUU_TAM
MOVLW .8
MOVWF SO_DICH

MOVF DIV,W
CPFSLT SO_CHIA ;NHAY NEU SO_CHIA < DIV
BRA KET_THUC
LOOP
BCF STATUS,C
RLCF DIV ;BIT7 OF DIV VAO CO C VA CO C VA BIT0 CUA DIV
RLCF LUU_TAM ;BIT7 OF DIV VAO BIT0 CUA LUU_TAM
MOVF LUU_TAM,W
CPFSEQ SO_CHIA
BRA NO_BANG
BRA BANG
NO_BANG
MOVF LUU_TAM,W
CPFSLT SO_CHIA ;NHAY NEU SO_CHIA < LUU_TAM (XEM SO DA DICH >SO CHIA CHUA)
BRA TTUC ;NO :THUONG SO=0 VA LUU VAO KQ_CHIA
BANG
MOVF SO_CHIA,W ;YES:THUONG SO=1 VA LUU VAO KQ_CHIA
SUBWF LUU_TAM,1 ;(LUU_TAM)-(SO_CHIA) LUU VAO LUU_TAM(SO_DU)
MOVLW 0X01
ADDWF DIV,1 ;DICH 1 VAO BIT0 CUA DIV-CHINH LA KQ_CHIA
TTUC
MOVFF LUU_TAM,SO_DU
MOVFF DIV,KQ_CHIA
DECFSZ SO_DICH,1
BRA LOOP
KET_THUC
END

anchovy
13-11-2007, 11:57 AM
Đây là phép chia 8 bit cho 8 bit lấy về tham khảo nhe bạn 16 bit cũng tương tự như vậy thôi:

#include <p18F4431.inc>
org 0x000000
SO_CHIA EQU 0X81
SO_DU EQU 0X82
DIV EQU 0X83
SO_DICH EQU 0X84
LUU_TAM EQU 0X85
KQ_CHIA EQU 0X86
MAIN
MOVLW .15
MOVWF DIV
MOVLW .10
MOVWF SO_CHIA

CLRF KQ_CHIA
CLRF SO_DU
CLRF LUU_TAM
MOVLW .8
MOVWF SO_DICH

MOVF DIV,W
CPFSLT SO_CHIA ;NHAY NEU SO_CHIA < DIV
BRA KET_THUC
LOOP
BCF STATUS,C
RLCF DIV ;BIT7 OF DIV VAO CO C VA CO C VA BIT0 CUA DIV
RLCF LUU_TAM ;BIT7 OF DIV VAO BIT0 CUA LUU_TAM
MOVF LUU_TAM,W
CPFSEQ SO_CHIA
BRA NO_BANG
BRA BANG
NO_BANG
MOVF LUU_TAM,W
CPFSLT SO_CHIA ;NHAY NEU SO_CHIA < LUU_TAM (XEM SO DA DICH >SO CHIA CHUA)
BRA TTUC ;NO :THUONG SO=0 VA LUU VAO KQ_CHIA
BANG
MOVF SO_CHIA,W ;YES:THUONG SO=1 VA LUU VAO KQ_CHIA
SUBWF LUU_TAM,1 ;(LUU_TAM)-(SO_CHIA) LUU VAO LUU_TAM(SO_DU)
MOVLW 0X01
ADDWF DIV,1 ;DICH 1 VAO BIT0 CUA DIV-CHINH LA KQ_CHIA
TTUC
MOVFF LUU_TAM,SO_DU
MOVFF DIV,KQ_CHIA
DECFSZ SO_DICH,1
BRA LOOP
KET_THUC
END

co the giai thich lenh nay "MOVLW .15" giup minh dc ko minh moi hoc pic nen ko hieu

david
13-11-2007, 04:48 PM
.15 là số thập phân thôi bạn ạ

anchovy
21-11-2007, 08:55 PM
cảm ơn bạn mình hiểu rồi.