keegan3d keegan3d - 1 year ago 164
Swift Question

Swift generic number types and math

I'm trying to wrap my head around the ins and outs of Swift generics and make some common math functions. I'm trying to implement a

function, but not quite sure the best way to get it working using generics.

Here's what my
function looks like:

func mod<N: NumericType, I: IntegerType>(_ x: N, _ y: I) -> N {
return x - y * floor(x/y)

But I'm getting this error:

error: binary operator '/' cannot be applied to operands of type 'N' and 'I'
return x - y * floor(x/y)

And here's my
declaration for decimal and integer type numbers:

protocol NumericType: Comparable {
static func +(lhs: Self, rhs: Self) -> Self
static func -(lhs: Self, rhs: Self) -> Self
static func *(lhs: Self, rhs: Self) -> Self
static func /(lhs: Self, rhs: Self) -> Self
static func %(lhs: Self, rhs: Self) -> Self

protocol DecimalType: NumericType {
init(_ v: Double)

protocol IntegerType: NumericType {
init(_ v: Int)

extension CGFloat : DecimalType { }
extension Double : DecimalType { }
extension Float : DecimalType { }

extension Int : IntegerType { }
extension Int8 : IntegerType { }
extension Int16 : IntegerType { }
extension Int32 : IntegerType { }
extension Int64 : IntegerType { }
extension UInt : IntegerType { }
extension UInt8 : IntegerType { }
extension UInt16 : IntegerType { }
extension UInt32 : IntegerType { }
extension UInt64 : IntegerType { }

Answer Source

As of Swift 3, all floating point types conform to FloatingPoint, and all integer types conform to Integer. Both protocols define the basic arithmetic operations like +,-,*,/. Also the floor() function is defined for FloatingPoint arguments.

Therefore in your case I would define two implementations, one for integers and one for floating point values:

func mod<N: Integer>(_ x: N, _ y: N) -> N {
    return x - y * (x/y) // or just: return x % y

func mod<N: FloatingPoint>(_ x: N, _ y: N) -> N {
    return x - y * floor(x/y)

FloatingPoint has also a truncatingRemainder method, a.truncatingRemainder(b) is the "floating point equivalent" to a % b for integers. It gives the gives the same result as your mod function if both operands have the same sign.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download