quotient(3scm)

πŸ“¦ version 0-unstable-2024-02, in nixpkgs unstable

πŸ’… quotient, remainder, modulo β€” number-theoretic integer division (the quotient(3scm) page, bestie)

okay so. three whole procedures today, and they're about number-theoretic integer division, which sounds scary but honestly it's just "dividing integers, but fancy." you got this. πŸŽ€

✨ LIBRARY ✨

Import from wherever your Scheme lives, queen:

(import (rnrs r5rs))                ;R6RS
(import (scheme r5rs))              ;R7RS
(import (scheme base))              ;R7RS

✨ SYNOPSIS ✨

(quotient n1 n2)
(remainder n1 n2)
(quotient n1 n2)
(remainder n1 n2)
(modulo n1 n2)

wait, that's not right β€” let me do it properly, no typos allowed:

(quotient n1 n2)
(remainder n1 n2)
(modulo n1 n2)

✨ DESCRIPTION ✨

so these three implement number-theoretic (integer) division. n2 must be non-zero β€” like, non-negotiable, do not come for her with a zero, she will not be okay with it. πŸ’€

if n1/n2 is an integer object, it's giving "clean division, no crumbs":

(quotient n1 n2)  => n1/n2
(remainder n1 n2) => 0
(modulo n1 n2)    => 0

if n1/n2 is not an integer object, then:

(quotient n1 n2)  => nq
(remainder n1 n2) => nr
(modulo n1 n2)    => nm

where, and this is the part you screenshot:

  • nq is n1/n2 rounded towards zero
  • 0 < abs(nr) < abs(n2)
  • 0 < abs(nm) < abs(n2)
  • nr and nm differ from n1 by a multiple of n2
  • nr has the same sign as n1
  • nm has the same sign as n2

and consequently β€” bestie this is the iconique identity, the main character of the whole page β€” for integer objects n1 and n2 with n2 not equal to 0:

(= n1 (+ (* n2 (quotient n1 n2))
         (remainder n1 n2)))
   => #t

provided all number objects involved in that computation are exact. (that qualifier is doing heavy lifting, don't ignore it πŸ™ˆ)

🧚 IMPLEMENTATION NOTES 🧚

R6RS has this reference implementation, and she's cute but she is missing type checks β€” so like, she's not judging your arguments, at all, which is generous and also slightly unhinged:

(define (sign n)
  (cond ((negative? n) -1)
        ((positive? n) 1)
        (else 0)))

(define (quotient n1 n2)
  (* (sign n1) (sign n2) (div (abs n1) (abs n2))))

(define (remainder n1 n2)
  (* (sign n1) (mod (abs n1) (abs n2))))

(define (modulo n1 n2)
  (* (sign n2) (mod (* (sign n2) n1) (abs n2))))

πŸ’– RETURN VALUES πŸ’–

each of these returns a single value β€” an integer object. one (1) whole result. she's lowkey low maintenance like that. 🫢

🌈 EXAMPLES 🌈

get into the negative-number of it all, this is where things get spicy:

(modulo 13 4)         =>  1
(remainder 13 4)      =>  1

(modulo -13 4)        =>  3
(remainder -13 4)     =>  -1

(modulo 13 -4)        =>  -3
(remainder 13 -4)     =>  1

(modulo -13 -4)       =>  -1
(remainder -13 -4)    =>  -1

(remainder -13 -4.0)  =>  -1.0   ; inexact

not the -13 erasure!! watch the signs, she's flipping them on purpose. πŸ’…

πŸ¦‹ APPLICATION USAGE πŸ¦‹

both R6RS and R7RS ship these procedures for compatibility β€” they're the legacy besties you keep around. but highkey they have often unexpected behavior when one of the arguments is negative. 😭

unless you know you need something else, you should probably prefer Euclidean division. see div-and-mod(3scm).

like, fr fr, go look at div-and-mod(3scm) first. i'm serious.

πŸ“ COMPATIBILITY πŸ“

R7RS implementations do not need to provide inexact integers, and the integer range may be reduced β€” but otherwise these procedures should work the same everywhere. slay for portability, honestly. ✨

πŸ’€ ERRORS πŸ’€

these procedures can raise exceptions with the following condition types:

  • &assertion (R6RS) β€” the wrong number of arguments was passed, or an argument was outside its domain.
  • R7RS β€” the assertions described above are errors. implementations may signal an error, extend the procedure's domain of definition to include such arguments, or fail catastrophically. (yes. catastrophically. no i'm not being dramatic, that's the actual wording 🌸)

πŸ‘‘ SEE ALSO πŸ‘‘

⭐ STANDARDS ⭐

R4RS, IEEE Scheme, R5RS, R6RS, R7RS β€” she's certified, she's been through every board, iconic behavior only.

πŸŽ€ HISTORY πŸŽ€

these procedures first appeared in R2RS. Scheme previous to R2RS, running on MacLisp, also had similar quotient and remainder procedures. they became legacy procedures in both R6RS and R7RS. so yeah, she's a veteran, she's seen things, respect her. 🫑

πŸ’œ AUTHORS πŸ’œ

this page is part of the scheme-manpages project. it includes materials from the RnRS documents. more information can be found at https://github.com/schemedoc/manpages/.

πŸ™ˆ BUGS πŸ™ˆ

depending on how these procedures are used, programs that use them may behave unexpectedly when one of the arguments is negative. that's it. that's the bug. negative numbers stay breaking hearts. πŸ’”


and that's the page, bestie! πŸ§šβ€β™€οΈβœ¨ this one's from the Scheme Programmer's Manual, dated 2022-04-12, quotient(3scm) β€” go forth and divide responsibly, and please, for me, check your signs. πŸ’–πŸŒΈπŸ¦‹

πŸ“¦ where this page comes from