Euclidean Division With Simultaneous Quotient And Remainder

  For the difference between Euclidean and truncated resuls and code compare with Trancate division.

A screen capture of the demo results.

Note - The last two lines of LONG and QUAD shows the difference between Euclidean and truncate with remainder results.

Source Code

  The Euclidean Division functions should compile and run as-is in any version of PowerBASIC from PBWin 8 and PBCC 4 to PBWin 10 and PBCC 6, maybe earier. Compiling with the PBMAIN function, the demonstration, requires PBWin 10 Will compile in either PBWin 10 or PBCC 6. The FUNCTIONs can be SUBs instead. To retain divide by zero detection replace "FUNCTION = %err_divisionbyzero" with "ERROR %err_divisionbyzero".

''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

Source and compiled code partial copyleft (ↄ), the limitation is you may not claim creation and attempt to copyright it.
This page is copyright © 2026, all rights reserved Dale Yarker.

Created on 30 August 2026.

To Dale's Notebook
go to Dale's Notebook index
To Programs
go to Programs index