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 mod
function, but not quite sure the best way to get it working using generics.
Here's what my mod
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 NumericType
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 { }
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.
static func /(lhs: Self, rhs: Self) -> Self
This means both lhs
and rhs
has to be of the same type .
In x / y
, x
is of the type N
, and y
is of type I
. So x
and y
have different types and therefore x / y
does not work.
You need to cast y
from I
to N
first:
let numericY = N(integer: y)
return x - numericY * floor(x / numericY)
which means your NumericType need to be able to initialize from an IntegerType, besides having +
, -
, *
, /
, %
.
protocol NumericType: Comparable {
init<I: IntegerType>(integer: I)
...
}
(Also, floor<N: NumericType>(n: N) -> N
should exist to make the whole expression compile.)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.