Hacker News new | past | comments | ask | show | jobs | submit login
Mod Function and Negative Numbers (2000) (mathforum.org)
30 points by booleandilemma on Oct 21, 2018 | hide | past | favorite | 15 comments



Julia goes the ADA way, supporting both. There's

    div(x,y)   # truncated division; quotient rounded towards zero
    fld(x,y)   # floored division; quotient rounded towards -Inf
and correspondingly

    rem(x,y)   # remainder; satisfies x == div(x,y)*y + rem(x,y); sign matches x
    mod(x,y)   # modulus; satisfies x == fld(x,y)*y + mod(x,y); sign matches y
and the convenience functions

    divrem(x,y) # returns (div(x,y),rem(x,y))  ## Lotus 123 convention
    fldmod(x,y)	# returns (fld(x,y),mod(x,y))  ## Excel convention
(There's also mod1 and fld1, and there's mod2pi(x) which is more precise than mod(x, 2pi).)


I run into this issue in javascript all the time. I want a number to basically act like pacman leaving the left or right side of a screen. pure sawtooth function. unfortunately js’s % operator mirrors at zero. so i always end up having to search for this:

    Number.prototype.mod = function(n) {
      return ((this % n) + n) % n;
    }


Agreed. In my experience, people want to use this modulo operator (e.g. for implementing a ring buffer or wrap-around as you mentioned), but many languages use the other modulo which leads to all sorts of bugs. It doesn’t make sense to me since this modulo is more natural from both a mathematical and an engineering perspective.


It’s because that’s the way CPUs / C do it. Many other language implementors are too lazy to fix it.

I have often been thankful that Python does the right thing, and often frustrated that Javascript does not.


For javascript mod I use these:

  function modn(a,b){ return a-Math.round(a/b)*b }
  // this returns in the cycle -0.5 to 0.5

  function modp(a,b){ return a-Math.floor(a/b)*b }
  // this returns 0 to 1 (times the cycle `b`)
They can actually run faster than the % operator for some reason, although not if put on Numbers prototype which is still quite slow on latest engines.

I ran a quick check on possible rounding differences with % - compared results of a few million very large random number inputs:

For positive Integers modp(a,b) returns identically to a%b

For positive reals 8% of returns differ by about 1 ulp.


at very large or very small scales, you expect some level of innaccuracy for any IEEE float op. acceptable level of error always depends on what the program is aiming to do I suppose.


Right, I just wondered about getting 0.00000000001 instead of 0 or the like, but that doesn't seem to happen with modest integer inputs.


Haskell supports both. The documentation explains the two pretty clearly, IMO:

    quot :: a -> a -> a 

      integer division truncated toward zero

    rem :: a -> a -> a 

      integer remainder, satisfying

        (x `quot` y)*y + (x `rem` y) == x

    div :: a -> a -> a 

      integer division truncated toward negative infinity

    mod :: a -> a -> a 

      integer modulus, satisfying

       (x `div` y)*y + (x `mod` y) == x
Here's an example

    ghci> (-340) `divMod` 60
    (-6,20)
    ghci> (-340) `quotRem` 60
    (-5,-40)


> integer division truncated toward negative infinity

Truncated?


See also “Mod and remainder are not the same” discussed here recently:

https://news.ycombinator.com/item?id=17817758


I find true module to be an insanely useful operator. Python negative indexing (array[-1]) is essentially that. I’ve proposed it to swift but people didn’t see the point https://forums.swift.org/t/double-modulo-operator/2718


Python negative indexing isn't modulo. It's just shorthand for array[len(array)-i].

  >>> a = [1, 2, 3]
  >>> a[-1]
  3
  >>> a[-2]
  2
  >>> a[-3]
  1
  >>> a[-4]
  Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  IndexError: list index out of range


The problem is that you need to have a conditional to figure out if I is negative or not. With modulo it’s all the same.


But you want array[len(array)] to throw an error rather than return array[0], so modulo isn't the right operator.


It is a sad thing but there is no standard: https://en.wikipedia.org/wiki/Modulo_operation.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: