Negative number modulo in swift

If what you are really after is capturing a number between 0 and b, try using this:

infix operator %%

extension Int {
    static  func %% (_ left: Int, _ right: Int) -> Int {
        if left >= 0 { return left % right }
        if left >= -right { return (left+right) }
        return ((left % right)+right)%right
    }
}

print(-1 %% 3) //prints 2

This will work for all value of a, unlike the the previous answer while will only work if a > -b.

I prefer the %% operator over just overloading %, as it will be very clear that you are not doing a true mod function.

The reason for the if statements, instead of just using the final return line, is for speed, as a mod function requires a division, and divisions are more costly that a conditional.


From the Language Guide - Basic Operators:

Remainder Operator

The remainder operator (a % b) works out how many multiples of b will fit inside a and returns the value that is left over (known as the remainder).

The remainder operator (%) is also known as a modulo operator in other languages. However, its behavior in Swift for negative numbers means that it is, strictly speaking, a remainder rather than a modulo operation.

...

The same method is applied when calculating the remainder for a negative value of a:

-9 % 4   // equals -1

Inserting -9 and 4 into the equation yields:

-9 = (4 x -2) + -1

giving a remainder value of -1.

In your case, no 3 will fit in 1, and the remainder is 1 (same with -1 -> remainder is -1).


The Swift remainder operator % computes the remainder of the integer division:

a % b = a - (a/b) * b

where / is the truncating integer division. In your case

(-1) % 3 = (-1) - ((-1)/3) * 3 = (-1) - 0 * 3 = -1

So the remainder has always the same sign as the dividend (unless the remainder is zero).

This is the same definition as required e.g. in the C99 standard, see for example Does either ANSI C or ISO C specify what -5 % 10 should be?. See also Wikipedia: Modulo operation for an overview how this is handled in different programming languages.

A "true" modulus function could be defined in Swift like this:

func mod(_ a: Int, _ n: Int) -> Int {
    precondition(n > 0, "modulus must be positive")
    let r = a % n
    return r >= 0 ? r : r + n
}

print(mod(-1, 3)) // 2

Tags:

Ios

Swift