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

Cos*_*ows 91 xcode modulus ios swift swift3

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

错误:%不可用:改为使用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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*n R 159

CMTimeGetSeconds()返回一个浮点数(Float64aka Double).在Swift 2中,您可以计算浮点除法的余数

let rem = 2.5 % 1.1
print(rem) // 0.3
Run Code Online (Sandbox Code Playgroud)

在Swift 3中,这是完成的

let rem = 2.5.truncatingRemainder(dividingBy: 1.1)
print(rem) // 0.3
Run Code Online (Sandbox Code Playgroud)

适用于您的代码:

let totalSeconds = CMTimeGetSeconds(self)
let hours = Int(totalSeconds / 3600)
let minutes = Int((totalSeconds.truncatingRemainder(dividingBy: 3600)) / 60)
let seconds = Int(totalSeconds.truncatingRemainder(dividingBy: 60))
Run Code Online (Sandbox Code Playgroud)

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

let totalSeconds = Int(CMTimeGetSeconds(self)) // Truncate to integer
// Or:
let totalSeconds = lrint(CMTimeGetSeconds(self)) // Round to nearest integer
Run Code Online (Sandbox Code Playgroud)

然后下一行简化为

let hours = totalSeconds / 3600
let minutes = (totalSeconds % 3600) / 60
let seconds = totalSeconds % 60
Run Code Online (Sandbox Code Playgroud)


ric*_*ter 23

%模数运算符仅被定义为整数类型.对于浮点类型,您需要更加具体地了解所需的IEEE 754除法/余数行为,因此您必须调用方法:remainder或者truncatingRemainder.(如果你正在进行浮点数学运算,你实际上需要关心这个,还有很多其他的东西,否则你会得到意想不到/糟糕的结果.)

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

根据您希望CMTime在UI中显示值的方式,最好提取秒值并将其传递给NSDateFormatterNSDateComponentsFormatter获得适当的语言环境支持.


eon*_*ist 9

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

这个语法是在苹果官方迅速邮件列表实际上建议这里,但由于某种原因,他们选择了一个不太优雅的语法.

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)
}
Run Code Online (Sandbox Code Playgroud)

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

  • @GitSync模运算仅适用于整数.你在谈论剩余.十进制值有两种类型的余数.这就是Swift决定明确操作的原因.在double值上计算整数余数(*截断余数*)并不常见. (5认同)
  • @JakubTruhlář......男,Thx.IMO这是我最好的快速3迁移修复程序.无法相信人们投票支持它.Modulo是一个如此重要的概念,并且在每个具有算术的代码簿中都被认为是.使它冗长是没有意义的,因为代码中的算术应该尽可能紧凑地编写.当你可以看到完整的图像反对理解个体变量的含义时,我们对理解算术的认知能力就会提高.IMO全面的变量命名在业务逻辑中很重要,但在算术中则不然,恰恰相反. (3认同)
  • @GitSync Modulo是一个重要的概念,但它只存在于整数.你应该明白其中的区别. (2认同)