简体   繁体   English

Swift通用数字类型和数学

[英]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. 我试图围绕Swift泛型的来龙去做,并制作一些常见的数学函数。 I'm trying to implement a mod function, but not quite sure the best way to get it working using generics. 我正在尝试实现一个mod函数,但不太确定使用泛型使其工作的最佳方法。

Here's what my mod function looks like: 这是我的mod函数的样子:

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: 这是我的十进制和整数类型数字的NumericType声明:

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 . 从Swift 3开始,所有浮点类型都符合FloatingPoint ,所有整数类型都符合Integer Both protocols define the basic arithmetic operations like +,-,*,/. 两种协议都定义了基本的算术运算,如+, - ,*,/。 Also the floor() function is defined for FloatingPoint arguments. 另外, floor()函数是为FloatingPoint参数定义的。

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. FloatingPoint还有一个truncatingRemainder方法, a.truncatingRemainder(b)是整数a % b的“浮点等价”。 It gives the gives the same result as your mod function if both operands have the same sign. 如果两个操作数具有相同的符号,则它给出与mod函数相同的结果。

static func /(lhs: Self, rhs: Self) -> Self

This means both lhs and rhs has to be of the same type . 这意味着lhsrhs必须属于同一类型

In x / y , x is of the type N , and y is of type I . x / yxN型, yI型。 So x and y have different types and therefore x / y does not work. 所以xy不同的类型 ,因此x / y不起作用。

You need to cast y from I to N first: 你需要投yIN第一:

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 + , - , * , / , % . 这意味着你的NumericType需要能够从IntegerType初始化,除了有+-*/%

protocol NumericType: Comparable {
    init<I: IntegerType>(integer: I)
    ...
}

(Also, floor<N: NumericType>(n: N) -> N should exist to make the whole expression compile.) (另外, floor<N: NumericType>(n: N) -> N应该存在以使整个表达式编译。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM