我正在创建一些实用程序类,用于存储数值(Int,Float,Double等)。它也具有最小值和最大值。
我需要将值转换为百分比。
因此,我在Playground上编写了以下类:
import UIKit
class Series<T: SignedNumeric> {
let minValue: T
let maxValue: T
var datas: [T] = []
let range: T
init(minValue: T, maxValue: T) {
self.minValue = minValue
self.maxValue = maxValue
self.range = (maxValue - minValue)
self.datas = []
}
func percent(value: T) -> Float {
let v: Float = value as! Float
let m: Float = minValue as! Float
let r: Float = range as! Float
return (v - m) / r
}
}
let s = Series<Int>(minValue: -100, maxValue: 100)
s.datas = [20, 0, 40, -100, 100]
Float(s.datas[0] - s.minValue) / Float(s.range)
Float(s.datas[1] - s.minValue) / Float(s.range)
Float(s.datas[2] - s.minValue) / Float(s.range)
Float(s.datas[3] - s.minValue) / Float(s.range)
Float(s.datas[4] - s.minValue) / Float(s.range)
s.percent(value: s.datas[0]) // ERROR !!!
当调用s.percent(value:s.datas [0])时,它崩溃了。
如何编写percent()函数?
并非每个SignedNumeric
都可以转换为Float
。回想一下,要成为SignedNumeric
,您必须能够:
Comparable
和Numeric
最后4个要求全部继承自Numeric
。我们可以轻松地构建自己的类型来执行所有这些操作。这是一个人为的例子:
struct MyNumber: SignedNumeric, Comparable {
private var secret: [String]
private var isNegative: Bool
private var number: Int { secret.count }
static func *= (lhs: inout MyNumber, rhs: MyNumber) {
lhs = lhs * rhs
}
static func * (lhs: MyNumber, rhs: MyNumber) -> MyNumber {
MyNumber(secret: Array(repeating: "", count: lhs.number * rhs.number), isNegative: lhs.isNegative != rhs.isNegative)
}
init(integerLiteral value: Int) {
let int = value
isNegative = int < 0
secret = Array(repeating: "", count: abs(int))
}
static func < (lhs: MyNumber, rhs: MyNumber) -> Bool {
lhs.number < rhs.number
}
init?<T>(exactly source: T) where T : BinaryInteger {
guard let int = Int(exactly: source) else {
return nil
}
self.init(integerLiteral: int)
}
var magnitude: MyNumber {
MyNumber(secret: secret, isNegative: false)
}
static func - (lhs: MyNumber, rhs: MyNumber) -> MyNumber {
if lhs < rhs {
return -(rhs - lhs)
} else {
return MyNumber(secret: Array(repeating: "", count: lhs.number - rhs.number))
}
}
prefix static func - (operand: MyNumber) -> MyNumber {
MyNumber(secret: operand.secret, isNegative: !operand.isNegative)
}
mutating func negate() {
isNegative.toggle()
}
init(secret: [String], isNegative: Bool = false) {
self.secret = secret
self.isNegative = isNegative
}
typealias Magnitude = MyNumber
static func + (lhs: MyNumber, rhs: MyNumber) -> MyNumber {
MyNumber(secret: lhs.secret + rhs.secret)
}
typealias IntegerLiteralType = Int
}
<插入在这里进行转换的人>到底是怎么知道要转换MyNumber
为Float
,它必须做的Float(aMyNumber.secret.count)
呢?更不用说这secret
是私人的。
另一方面,Float.init
确实知道如何将BinaryFloatingPoint
s和BinaryInteger
s转换为Float
,因为那些协议定义了必要的属性,以便Float.init
可以理解它们的表示方式。例如,BinaryInteger
S被表示words
,这是一个RandomAccessCollection
的UInt
S,由索引Int
秒。
我建议您只将该percent
方法添加到Series
实际有意义的类型中:
extension Series where T : BinaryInteger {
func percent(value: T) -> Float {
let v: Float = Float(value)
let m: Float = Float(minValue)
let r: Float = Float(range)
return (v - m) / r
}
}
海事组织,这对任何人都有意义T : FloatingPoint
,而不仅仅是T : BinaryFloatingPoint
:
extension Series where T : FloatingPoint {
func percent(value: T) -> T {
let v = value
let m = minValue
let r = range
return (v - m) / r
}
}
由于也FloatingPoint
支持除法,因此您无需转换为Float
!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句