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

What does "% is unavailable: Use truncatingRemainder instead" mean?

我在使用代码进行扩展时遇到以下错误,我不确定他们是要求使用不同的运算符还是根据 Internet 搜索修改表达式中的值。

错误:% 不可用:改用 truncatingRemainder

分机号:[=​​11=]

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)
        }
    }
}

设置分秒变量时出现错误。

CMTimeGetSeconds() returns 一个浮点数(Float64 又名 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

% 模数运算符仅为整数类型定义。对于浮点类型,您需要更具体地了解您想要的 IEEE 754 division/remainder 行为类型,因此您必须调用一个方法:remainder or truncatingRemainder. (If you're doing floating-point math you actually need to care about this, and lots of other stuff,否则您会得到意想不到的/不好的结果.)

如果你真的打算做整数取模,你需要在使用%之前将CMTimeGetSeconds的return值转换为整数。 (请注意,如果你这样做,你会去掉小数秒......这取决于你在哪里使用 CMTime 这可能很重要。例如,你想要 minutes:seconds:frames 吗?)

根据您想在 UI 中显示 CMTime 值的方式,提取秒值并将其传递给 NSDateFormatter or NSDateComponentsFormatter 可能会更好,这样您就可以获得适当的语言环境支持.

恢复 swift 3:

中的简单模语法

这种语法实际上是在 Apple 的官方 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)
}

这个简单的 swift 3 迁移技巧是更全面的 swift 3 迁移指南的一部分,具有许多见解(35k loc / 8 天的迁移)http://eon.codes/blog/2017/01/12/swift-3-migration/

我发现以下在 Swift 3 中有效:

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

其中 totalSecondsTimeInterval (Double)。

没有必要为浮点数创建单独的模运算符,除非您认为这样做可以使代码更安全。您可以重载 % 运算符以接受浮点数,如下所示:

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

用法

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

您现在可以将 % 与任何两个相同类型的浮点数一起使用。