“%不可用:使用truncatingRemainder”是什么意思?

时间:2016-11-08 19:52:33

标签: ios swift xcode swift3 modulus

使用扩展代码时出现以下错误,我不确定他们是否要求使用其他运算符或根据互联网搜索修改表达式中的值。

错误:%不可用:改为使用truncatingRemainder

分机代码:

extension CMTime {
    var durationText:String {
        let totalSeconds = CMTimeGetSeconds(self)
        let hours:Int = Int(totalSeconds / 3600)
        let minutes:Int = Int(totalSeconds % 3600 / 60)
        let seconds:Int = Int(totalSeconds % 60)

        if hours > 0 {
            return String(format: "%i:%02i:%02i", hours, minutes, seconds)
        } else {
            return String(format: "%02i:%02i", minutes, seconds)
        }
    }
}

设置分钟和秒变量时会发生错误。

5 个答案:

答案 0 :(得分:145)

CMTimeGetSeconds()返回一个浮点数(Float64 aka Double)。在Swift 2中你可以计算出

的浮点除法的余数
let rem = 2.5 % 1.1
print(rem) // 0.3

在Swift 3中,这是用

完成的
let rem = 2.5.truncatingRemainder(dividingBy: 1.1)
print(rem) // 0.3

应用于您的代码:

let totalSeconds = CMTimeGetSeconds(self)
let hours = Int(totalSeconds / 3600)
let minutes = Int((totalSeconds.truncatingRemainder(dividingBy: 3600)) / 60)
let seconds = Int(totalSeconds.truncatingRemainder(dividingBy: 60))

但是,在这种特殊情况下,转换持续时间会更容易 首先是一个整数:

let totalSeconds = Int(CMTimeGetSeconds(self)) // Truncate to integer
// Or:
let totalSeconds = lrint(CMTimeGetSeconds(self)) // Round to nearest integer

接下来的行简化为

let hours = totalSeconds / 3600
let minutes = (totalSeconds % 3600) / 60
let seconds = totalSeconds % 60

答案 1 :(得分:20)

%模数运算符仅针对整数类型定义。对于浮点类型,您需要更加具体地了解所需的IEEE 754除法/余数行为,因此您必须调用方法:remaindertruncatingRemainder。 (如果你正在做浮点数学,你实际上需要关心这个,lots of other stuff,否则你会得到意想不到的坏结果。)

如果您确实打算执行整数模数,则需要在使用CMTimeGetSeconds之前将%的返回值转换为整数。 (请注意,如果你这样做,你将会缩短小数秒......取决于你使用CMTime可能很重要的地方。你想要分钟:秒:帧,例如?)

根据您希望在UI中显示CMTime值的方式,最好提取秒值并将其传递给NSDateFormatterNSDateComponentsFormatter,以便获得适当的区域设置支持

答案 2 :(得分:9)

在swift 3中返回简单的模数语法:

这种语法实际上是在Apples官方swift邮件列表here上提出的,但由于某种原因,他们选择了不太优雅的语法。

infix operator %%/*<--infix operator is required for custom infix char combos*/
/**
 * Brings back simple modulo syntax (was removed in swift 3)
 * Calculates the remainder of expression1 divided by expression2
 * The sign of the modulo result matches the sign of the dividend (the first number). For example, -4 % 3 and -4 % -3 both evaluate to -1
 * EXAMPLE: 
 * print(12 %% 5)    // 2
 * print(4.3 %% 2.1) // 0.0999999999999996
 * print(4 %% 4)     // 0
 * NOTE: The first print returns 2, rather than 12/5 or 2.4, because the modulo (%) operator returns only the remainder. The second trace returns 0.0999999999999996 instead of the expected 0.1 because of the limitations of floating-point accuracy in binary computing.
 * NOTE: Int's can still use single %
 * NOTE: there is also .remainder which supports returning negatives as oppose to truncatingRemainder (aka the old %) which returns only positive.
 */
public func %% (left:CGFloat, right:CGFloat) -> CGFloat {
    return left.truncatingRemainder(dividingBy: right)
}

这个简单的快速3迁移提示是更全面的swift 3迁移指南的一部分,其中包含许多见解(35k loc / 8天迁移)http://eon.codes/blog/2017/01/12/swift-3-migration/

答案 3 :(得分:3)

我发现以下内容适用于Swift 3:

    let minutes = Int(floor(totalSeconds / 60))
    let seconds = Int(totalSeconds) % 60

其中totalSecondsTimeIntervalDouble)。

答案 4 :(得分:3)

除非您认为它使代码更安全,否则无需为浮点数创建单独的模运算符。您可以重载%运算符以接受浮点数,如下所示:

func %<N: BinaryFloatingPoint>(lhs: N, rhs: N) -> N {
    lhs.truncatingRemainder(dividingBy: rhs)
}

用法

let a: Float80 = 10
let b: Float80 = 3
print(a % b)

您现在可以将%与相同轮胎的任意两个浮点数一起使用。