31.08.2026, 06:25
(This post was last modified: 31.08.2026, 06:31 by Dale Yarker.)
Euclidean division results for negative dividends are different from regular integer divide and MOD which are 2 operations.
These functions each return both quotient and remainder in BYREF variables.
The function for LONGs is assembly. For now the QUADs is BASIC; assembly will take more work.
This is also at https://www.yarker-dsyc.info/Programs/Mi...idDiv.html with a few more words.
To make a set tuncate functions are at https://www.yarker-dsyc.info/Programs/Mi...teDiv.html
These functions each return both quotient and remainder in BYREF variables.
The function for LONGs is assembly. For now the QUADs is BASIC; assembly will take more work.
This is also at https://www.yarker-dsyc.info/Programs/Mi...idDiv.html with a few more words.
To make a set tuncate functions are at https://www.yarker-dsyc.info/Programs/Mi...teDiv.html
Code:
''The remainder/modulo operation performed by Intel math coprocessors (FPREM
''and FPREM1 instructions) is not Euclidean, Intel's idiv assembly instruction
''is not Euclidean division. They are both IEEE Standard 754.
''In Euclidean division the remainder is never negative. For negative dividends
''the quotient is 1 different than expected.
''From Google- "An example use of Euclidean division with a negative dividend
''is finding a repeating time or calendar offset, such as calculating what hour
''of the day it was a certain number of hours ago.
#compile exe
#dim all
#if %def(%pb_cc32) 'if PBCC
#console off 'don't create a console window
#endif
'========================== Euclidean Division Of LONGs ========================
function EuclidDivide (byval Dividend as long, _
byval Divisor as long, _
byref Quotient as long, _
byref Remainder as long) as long
'
! mov ebx, Divisor
! cmp ebx, 0
! jne DoDivide
! mov function, %err_divisionbyzero
! jmp Done
DoDivide:
! mov esi, Quotient 'Quotient and Remainder pointers to registers
! mov edi, Remainder
'
! mov eax, Dividend 'load the dividend
! cdq 'sign-extend EAX into EDX:EAX
! idiv ebx 'EDX:EAX / ECX
'
'adjust to Euclidean results
! cmp edx, 0 'remainder < 0
! jl RmndrLT0
! jmp Results
RmndrLT0:
! cmp ebx, 0 'divisor > 0
! jg DvsrGT0
! add eax, 1
! sub edx, ebx
! jmp Results
DvsrGT0:
! sub eax, 1
! add edx, ebx
'
'set result variables
Results:
! mov [esi], eax
! mov [edi], edx
Done:
end function
'
'========================== Euclidean Division Of QUADs ========================
'For QUAD the only change is the type of the parameters.
function EuclidDivideQuad (byval Dividend as quad, _
byval Divisor as quad, _
byref Quotient as quad, _
byref Remainder as quad) as long
'------------------------
if Divisor = 0 then
Quotient = 0
Remainder = 0
function = %err_divisionbyzero
exit function
end if
'
Quotient = Dividend \ Divisor
Remainder = Dividend mod Divisor
'
if Remainder < 0 then
if Divisor > 0 then
Quotient -= 1
Remainder += Divisor
else
Quotient += 1
Remainder -= Divisor
end if
end if
end function
'
'/\/\/\/\/\/\/\/\/\/\/\ Demonstrate Euclidian Division /\/\/\/\/\/\/\/\/\/\/\/\
function pbmain () as long
local hTWin as dword
local QuotientQ, RemainderQ as quad
local Quotient, Remainder, ErrNum as long
local FmtLg, FmtQd as string
txt.window("Euclidian Division Demonstration", 200, 200, 18, 64) to hTWin
'
FmtLg = " #;-#; 0"
FmtQd = " ###########;-###########; 0"
'================================== Long =====================================
txt.print "type LONG"
ErrNum = EuclidDivide(9, 0, Quotient, Remainder)
txt.print " 9 / 0 = " + format$(Quotient, FmtLg) + " R" + _
format$(Remainder, FmtLg) + " error code = " + dec$(ErrNum, 2)
'
ErrNum = EuclidDivide(9, 4, Quotient, Remainder)
txt.print " 9 / 4 = " + format$(Quotient, FmtLg) + " R" + _
format$(Remainder, FmtLg) + " error code = " + dec$(ErrNum, 2)
'
ErrNum = EuclidDivide(9, -4, Quotient, Remainder)
txt.print " 9 / -4 = " + format$(Quotient, FmtLg) + " R" + _
format$(Remainder, FmtLg) + " error code = " + dec$(ErrNum, 2)
'
ErrNum = EuclidDivide(-9, 4, Quotient, Remainder)
txt.print "-9 / 4 = " + format$(Quotient, FmtLg) + " R" + _
format$(Remainder, FmtLg) + " error code = " + dec$(ErrNum, 2)
'
ErrNum = EuclidDivide(-9, -4, Quotient, Remainder)
txt.print "-9 / -4 = " + format$(Quotient, FmtLg) + " R" + _
format$(Remainder, FmtLg) + " error code = " + dec$(ErrNum, 2)
'
'================================== Quad =====================================
txt.print
txt.print "type QUAD"
ErrNum = EuclidDivideQuad(90000000000, 0, QuotientQ, RemainderQ)
txt.print " 90000000000 / 0 = " + _
format$(QuotientQ, FmtQd) + " R" + format$(RemainderQ, FmtQd) + _
" error code " + dec$(ErrNum, 2)
'
ErrNum = EuclidDivideQuad(90000000000, 40000000000, QuotientQ, RemainderQ)
txt.print " 90000000000 / 40000000000 = " + _
format$(QuotientQ, FmtQd) + " R" + format$(RemainderQ, FmtQd) + _
" error code " + dec$(ErrNum, 2)
'
ErrNum = EuclidDivideQuad(90000000000, -40000000000, QuotientQ, RemainderQ)
txt.print " 90000000000 / -40000000000 = " + _
format$(QuotientQ, FmtQd) + " R" + format$(RemainderQ, FmtQd) + _
" error code " + dec$(ErrNum, 2)
'
ErrNum = EuclidDivideQuad(-90000000000, 40000000000, QuotientQ, RemainderQ)
txt.print "-90000000000 / 40000000000 = " + _
format$(QuotientQ, FmtQd) + " R" + format$(RemainderQ, FmtQd) + _
" error code " + dec$(ErrNum, 2)
'
ErrNum = EuclidDivideQuad(-90000000000, -40000000000, QuotientQ, RemainderQ)
txt.print "-90000000000 / -40000000000 = " + _
format$(QuotientQ, FmtQd) + " R" + format$(RemainderQ, FmtQd) + _
" error code " + dec$(ErrNum, 2)
'
txt.print
txt.print
txt.color = &h0000C000
txt.print "Any key to close."
txt.waitkey$
txt.end
end function
