二元运算符' *'不能应用于'Float'类型的操作数和'浮动!'

时间:2017-02-15 13:01:00

标签: swift swift3

当我执行以下操作时:

let gapDuration = Float(self.MONTHS) * Float(self.duration) * self.gapMonthly;

我收到错误:

Binary operator '*' cannot be applied to operands of type 'Float' and 'Float!'

但是当我这样做时:

let gapDuration = 12 * Float(self.duration) * self.gapMonthly;

一切都很好。 我不知道这个错误告诉我的是什么。

self.gapMonthly的类型为Float!self.durationself.MONTHS的类型为Int!

1 个答案:

答案 0 :(得分:5)

我认为这是一个错误(至少,错误是误导性的),并且当试图在3个或更多表达式上使用二元运算符时,它似乎存在,这些表达式计算为给定类型,其中一个或多个这些表达式是该类型的隐式解包的可选项。

这简单地延伸了类型检查器,因为它必须考虑将IUO视为强选项的所有可能性(因为SE-0054编译器会将IUO视为强选项,如果它可以被类型检查为一个),同时试图为运营商找到正确的重载。

乍一看,它似乎与How can I concatenate multiple optional strings in swift 3.0?中显示的问题相似 - 但是该错误已在Swift 3.1中修复,但此错误仍然存​​在。

重现相同问题的最小例子是:

let a: Float! = 0

// error: Binary operator '*' cannot be applied to operands of type 'Float' and 'Float!'
let b = a * a * a

并且存在于*以外的其他二元运算符:

// error: Binary operator '+' cannot be applied to operands of type 'Float' and 'Float!'
let b = a + a + a

Float表达式中混合时(只要至少有一个Float!表达式保留),以及明确地将b注释为{{1}时,它仍然是可重现的}:

Float

let b: Float = a * a * a // doesn't compile

对此的一个简单修复是明确强制解包表达式中隐式解包的可选项:

let a: Float! = 0
let b: Int = 0
let c: Int = 0

let d: Float = a * Float(b) * Float(c) // doesn't compile

这减轻了类型检查器的压力,因为现在所有表达式都计算为let d = a! * Float(b) * Float(c) // compiles ,因此重载分辨率要简单得多。

虽然当然,如果Floata,这将会崩溃。一般情况下,您应该尝试避免使用隐式展开的选项,而是更喜欢使用强选项 - 而且,如@vadian says一样,在值为nil的情况下,始终使用非选项感。

如果你需要使用一个可选项并且不能100%确定它包含一个值,你应该在进行算术运算之前安全地打开它。一种方法是使用nil的{​​{3}}方法来传播可选性:

Optional

如果let a: Float! = 0 let b: Int = 0 let c: Int = 0 // the (a as Float?) cast is necessary if 'a' is an IUO, // but not necessary for a strong optional. let d = (a as Float?).map { $0 * Float(b) * Float(c) } 为非零,则a将初始化为展开后的值d乘以aFloat(b)的结果。但如果Float(c)a,则nil将初始化为d