Does anybody know how we can retrieve the fraction part of a division of two whole numbers using fixed point mathematics? I thought of a formula and it goes like this:

1. Divide dividend by the divisor. The quotient will be the whole part of the division.
2. (If there is a remainder) Divide the divisor by the remainder. Keep the quotient and the remainder.
3. (If there was a remainder) Divide 10 by the quotient of the division in the above stage.
4. The quotient of the second stage subtracted from the quotient of the above division will be the first digit of the fraction.

For example, divide 45 by 6:

1. 45 divided by 6 will yield the quotient 7. Keep this number.
2. The remainder of 45/6 = 3. Divide the divisor in the above stage (6) by 3 = 2, remainder = 0.
3. Divide 10 by the quotient of the above stage.10/2 = 5.
4. Subtract the remainder of the second stage from the quotient of the above stage 5-0 = 5.

So the result will be 7 (from the first stage) and with the fraction of .5 (from the 4th stage).

Or let?s say 68 divided by 14:

1. 68 divided by 14 yields the quotient of 4. Keep this number.
2. The remainder of 68/14 = 12. Divide the divisor of the above stage by 12. 14/12 yields the quotient of 1 and the remainder of 2.
3. Divide 10 by the quotient of the above stage which yields 10.
4. Subtract the remainder of the second stage from the quotient of the above stage which will yield 10-2=8.

Therefore the result will be 4 (from the first stage) and the fraction of 8 (from the 4th stage) = 4.8

However, the formula that I invented is not always accurate. There are some pitfalls to avoid and it won?t always yield the correct result. I was wondering if anybody knows of a better way to do this.

Here is the code that I have written for it:

``  MOV     EAX , Dividend  XOR     EDX , EDX  MOV     EBX , Divisor  DIV     EBX  MOV     Quotient , EAX  XOR     EAX , EAX  TEST    EDX , EDX  JZ      @NoFraction  MOV     EAX , Divisor  MOV     EBX , EDX  XOR     EDX , EDX  DIV     EBX  MOV     ECX , EDX  CMP     ECX , 1  JNE     @NotOne  XOR     ECX , ECX  @NotOne:  MOV     EBX , EAX  MOV     EAX , 10  XOR     EDX , EDX  DIV     EBX  SUB     EAX , ECX  @NoFraction:  MOV     Fraction , EAX``
Posted on 2007-04-14 04:14:08 by XCHG
You should simply simulate what you have learned in grade school. Just continue dividing the remainder multiplied by 10 by the initial divisor until the remainder is either 0 or you have the required number of decimal places.

However, the result will definitely not be in a format which could easily be reused for other math operations. You may gain an additional perspective on the subject of fixed point math from the following:

http://www.ray.masmcode.com/fixmath.html

Raymond
Posted on 2007-04-14 20:23:09 by Raymond
``pdec proto buf:DWORD,lo32:DWORD,hi32:DWORD,commas:DWORD,ljust:DWORDpower10 proc public uses ebx ecx n:dword    mov eax,1    mov ebx,n    mov ecx,10    or ebx,ebx    jz done  next:    mul ecx    sub ebx,1    jnz next  done:    retpower10 endppflt proc public uses ebx ecx edx esi buf:DWORD,num:DWORD,divisor:DWORD,commas:DWORD,ljust:DWORD,dig:DWORD    local whole:dword,frac:dword    mov eax,num    sub edx,edx    mov esi,buf    div divisor    mov ebx,edx    INVOKE pdec,esi,eax,0,commas,ljust ;prints the "whole" part    lstrlen esi    lea esi,    invoke power10,dig    mul ebx    div divisor    mov edx,dig    mov word ptr ,'.'  ;decimal point    or dl,80h    INVOKE pdec,esi,eax,0,0,edx  ;print the decimal part    retpflt endp``

Haven't used it much but seems to work OK.
Posted on 2007-04-15 02:39:26 by sinsi
Thank you Raymond. It is such a shame I had forgotten about that. Thank you sinsi.

I coded this function that returns the quotient of the division in EDX and the fraction part of the division in EAX just like a normal integer. For example, 654/32 = 20.4375. So EDX = 20 and EAX = 4375.

``; ??????????????????????????????????????????????????  __FixedDivision:    ; QWORD __FixedDivision (DWORD Dividend, DWORD Divisor); StdCall;    ; QWORD.DWORD#0 = Fraction    ; QWORD.DWORD#1 = Quotient    PUSH    EBX                                       ; Push the base index onto the stack    PUSH    ECX                                       ; Push the count register onto the stack    PUSH    ESI                                       ; Push the source index onto the stack    PUSH    EDI                                       ; Push the destination index onto the stack    PUSH    EBP                                       ; Push the base pointer onto the stack    MOV     EBP , ESP                                 ; Move the stack pointer to the base pointer    SUB     ESP , 0x00000008                          ; Allocate 8 bytes of the stack space    XOR     EAX , EAX                                 ; Clear the accumulator to put into the stack space    MOV     DWORD PTR  , EAX              ; * = Quotient = 0    MOV     DWORD PTR  , EAX              ; * = Fraction = 0 (We have 0.0 for now)    MOV     ESI , DWORD PTR               ; *ESI = The  parameter    TEST    ESI , ESI                                 ; We can't go on with a dividend equal to zero    JZ      .EP                                       ; Jump to the end of the procedure if Dividend is zero    MOV     EDI , DWORD PTR  ; Divisor    ; *EDI = The  parameter    TEST    EDI , EDI                                 ; We can not divide by zero    JZ      .EP                                       ; Jump to the end of the procedcure if Divisor is zero    MOV     ECX , 0x00000009                          ; We can only have 9 digits of fraction in the result    MOV     EAX , ESI                                 ; Get the Dividend in EAX    XOR     EDX , EDX                                 ; Set the High Order DWORD of the Dividend to zero    DIV     EDI                                       ; Divide the Dividend by the Divisor    MOV     DWORD PTR  , EAX              ; Get the Quotient in     TEST    EDX , EDX                                 ; See if there is a remainder    JZ      .EP                                       ; Jump to the end of the procedure if there are no fractions    LEA     ESI ,                         ; *ESI = Pointer to the Fraction part in the stack    .GetFraction:                                     ; Here we should get the fraction (EDX*10/Divisor)      LEA     EAX ,                       ; EAX = Remainder, Multiply EAX by 10, Step 1      LEA     EAX ,                 ; Multiply the remainder by 10, Step 2      XOR     EDX , EDX                               ; Clear the High Order DWORD of the Dividend      DIV     EDI                                     ; EAX = The next digit of the fraction part of the division      TEST    EAX , EAX                               ; See if the fraction part is zero      JZ      .EP                                     ; Jump to the end of the procedure if yes (We don't want zeros)      MOV     EBX , DWORD PTR                    ; Get the previous fraction in EBX      ADD     EBX , EBX                               ; Multiply the previous fraction by 10, Step 1      LEA     EBX ,                 ; Multiply the previous fraction by 10, Step 2      ADD     EBX , EAX                               ; Put the new fraction in the previous fraction part      MOV     DWORD PTR  , EBX                   ; Put the new fraction in the stack      DEC     ECX                                     ; Decrement the number of fraction digits we should get      JNZ     .GetFraction                            ; Keep extracting the fraction part while ECX > 0    .EP:                                              ; End of the procedure      MOV     EDX , DWORD PTR             ; *EDX holds the quotient now      MOV     EAX , DWORD PTR             ; *EAX holds the fraction part now      ADD     ESP , 0x00000008                        ; Deallocate 8 bytes of the stack space      POP     EBP                                     ; Restore the base pointer      POP     EDI                                     ; Restore the destination index      POP     ESI                                     ; Restore the source index      POP     ECX                                     ; Restore the count register      POP     EBX                                     ; Restore the base index    RET     0x08                                      ; Return to the calling procedure                                                      ; And sweep 2 parameters off the stack; ??????????????????????????????????????????????????``
Posted on 2007-04-16 01:41:10 by XCHG
XCHG

Sorry for the delay. I've been on the road for the past few days (migrating back up north).

In your .GetFraction: section, testing the content of EAX is the wrong thing to do (i.e. try it with 12/11 as an example). Instead, you should be testing the content of EDX (the remainder) after you have updated the fraction part and just before you decrement the counter for the number of decimal places.

Raymond
Posted on 2007-04-19 13:22:33 by Raymond