I'll leave that up to the user, Dr. Dri. Passing it as a string allows for large numbers and allows the user to create it anyway they like.
And yup, srod. It uses the Euclidean algorithim to find the GCD in order to reduce the fraction to it's simplest form. I looked it up on wikipedia
I have an ASM version that's slightly faster but it's clunky. I only did it to practice more asm stuffs.
Code: Select all
Procedure.s ToFractionASM(Value.s)
;
HoldResult.s
; String used to return the result.
HoldValue.l
; Used to temporarily store a value.
!MOV esi, dword[esp]
; Store the start of the string.
!DEC esi
;
!.Start:
; The start of the loop used to locate the decimal character.
!INC esi
; Increment to the next character.
!MOVSX eax, byte[esi]
; Store the current character.
!CMP eax, 0
!JNE @f
; Test for the eol character.
ProcedureReturn Value
; This is not a fraction. Exit the procedure. "Value/1" = "Value"
!@@:
; Character was not the eol character.
!CMP eax, 46
!JNE .NotDecimal
; Test for the decimal character.
;- Begin Conversion
!CMP esi, dword[esp]
!JE .BadValue
; There must be a numeric value before the decimal place.
!MOV edx, esi
; Store the address of the decimal character.
!MOV ebx, 0
; Used to store the numerator.
!MOV eax, 1
; Used powers to convert the string to a numeric.
!.LoopInteger:
; Loop used to convert numerator to value.
!DEC esi
;
!CMP esi, dword[esp]
!JB .ConvertDecimal
; Before the first numeral - done converting the integer.
!MOVSX edi, byte[esi]
; Store the ascii value in edi
!SUB edi, 48
; Convert the ascii code to it's numeric value.
!IMUL edi, eax
; Convert the number to it's place.
!ADD ebx, edi
; Increase the size of the numerator.
!IMUL eax, 10
; Increment ebp to the next power.
!JMP .LoopInteger
; Process the next character.
!.ConvertDecimal:
; Loop used to convert denominator to value.
!MOV esi, edx
; Point to the decimal place.
!@@:
!INC esi
!MOVSX edi, byte[esi]
!MOV [esp + 8], edi
!CMP edi, 0
!JNE @b
; Loop until the eol character.
!MOV edx, 0
; Used to store the denominator.
!MOV eax, 1
;
!.LoopDecimal:
; Begins the loop to convert the decimal to denominator.
!DEC esi
; Move to the last character in the string.
!MOVSX edi, byte[esi]
; Store the current numeral.
!CMP edi, 46
!JE .ConvertFinished
; Test for the decimal character.
!SUB edi, 48
; Convert the ascii code to it's numeric value.
!IMUL edi, eax
; Convert the number to it's place.
!ADD edx, edi
; Increase the size of the denominator.
!IMUL eax, 10
; Increment ebp to the next power.
!JMP .LoopDecimal
; Process the next character.
!.ConvertFinished:
;
!MOV edi, ebx
; Store the original integer value.
!MOV ebx, edx
;
!MOV edx, eax
; Store the denominator.
!MOV esi, ebx
!MOV ebp, edx
; esi will contain the original numerator while ebp contains the original denominator.
!MOV eax, ebx
!MOV ebx, edx
; Store the numerator and denomator
!CMP eax, ebx
!JA @f
; Test if the numerator is greater than the denominator.
!XCHG eax, ebx
; Swap the two if the denominator is larger than the numerator.
!@@:
; Start the loop to find the GCD.
!CDQ
;
!IDIV ebx
;
!CMP edx, 0
!JE @f
; When the remainder is zero, the GCD is located.
!MOV eax, ebx
!MOV ebx, edx
;
!JMP @b
; GCD is not found.
!@@:
; ebx now contains the GCD
!MOV dword[esp + 8], edi
HoldResult = Str(HoldValue) + " "
;
!MOV eax, esi
!CDQ
!IDIV ebx
!MOV dword[esp + 8], eax
HoldResult = HoldResult + Str(HoldValue)+"/"
!MOV eax, ebp
!CDQ
!IDIV ebx
!MOV dword[esp + 8], eax
HoldResult = HoldResult + Str(HoldValue)
;
!JMP .Finished
;
;- End Conversion
!.NotDecimal:
; Character was not the decimal character.
!CMP eax, 48
!JB .BadValue
!CMP eax, 57
!JA .BadValue
; Test to ensure the character is a numeric.
!JMP .Start
; Process the next character.
!.Finished:
;
ProcedureReturn HoldResult
;
!.BadValue:
; There is a problem with the value string (most likely non-numeric).
ProcedureReturn Value
; Return the value string.
EndProcedure
It's nothing great and I'm sure Psychophanta will be secretly laughing at me behind his computer
