「%が利用できない:代わりにtruncatingRemainderを使用する」とはどういう意味ですか?


103

拡張機能のコードを使用すると、次のエラーが表示されます。別の演算子を使用するのか、インターネット検索に基づいて式の値を変更するのかを知りません。

エラー:%は使用できません:代わりに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)
        }
    }
}

エラーは、分と秒の変数を設定するときに発生します。


1
CMTimeGetSecondsが浮動小数点を返すと思います
ゾンビ

3
これは、%オペレーターが利用できないため、truncatingRemainder代わりにメソッドなどの使用を検討する必要があることを意味します。
2016年

1
モジュロは使用できませんFloat64が、オンIntのみです。したがって:let minutes:Int = Int(totalSeconds) % 3600 / 60; let seconds:Int = Int(totalSeconds) % 60が正しい方法です。
holex 2017年

回答:


172

CMTimeGetSeconds()浮動小数点数(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

24

%剰余演算子は、整数のみのタイプのために定義されています。浮動小数点型の場合、必要なIEEE 754除算/剰余動作の種類をより具体的にする必要があるため、メソッドを呼び出す必要があります:remainderまたはtruncatingRemainder。(浮動小数点演算を行っている場合は、実際にこれや他の多くのことに注意する必要があります。そうしないと、予期しない/悪い結果が生じる可能性があります。)

実際に整数係数を使用する場合は、CMTimeGetSecondsを使用する前にの戻り値を整数に変換する必要があります%。(もしそうした場合、秒の小数部が省略されます...使用している場所によってはCMTime重要かもしれません。たとえば、分:秒:フレームが必要ですか?)

CMTimeUIでの値の表示方法によっては、秒の値を抽出して渡すNSDateFormatterNSDateComponentsFormatter、適切なロケールサポートを取得する方が適切な場合があります。


10

Swift 3の単純なモジュロ構文を復活させます。

この構文は実際にはAppleの公式の迅速なメーリングリストで提案されいましが、何らかの理由で、あまりエレガントでない構文を選択しました。

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 /


1
このAは、大丈夫です、興味深い情報を提供し、またQ.お答えしようとする
ヤクブTruhlář

3
@JakubTruhlář...男、Thx。IMOこれは、私の最も迅速な3移行の修正でした。人々が反対票を投じたなんて信じられない。Moduloはそのような重要な概念であり、算術を含むすべてのコードブックで考えられています。コード内の算術は可能な限りコンパクトに記述する必要があるため、冗長にしても意味がありません。個々の変数の意味を理解するのとは対照的に全体像を見ると、算数を理解する認知能力が高まります。IMO包括的な変数の命名はビジネスロジックでは重要ですが、算術演算では重要ではありません。逆です。
eonist 2017年

2
@GitSync Moduloは重要な概念ですが、整数の場合にのみ存在します。違いを理解する必要があります。
スルタン

5
@GitSyncモジュロ演算は整数に対してのみ存在します。あなたは残りについて話している。10進数値には2種類の剰余があります。そのため、Swiftは操作を明示的にすることにしました。double値で整数の剰余を計算する(剰余を切り捨てる)ことはあまり一般的ではありません。
スルタン

1
@GitSyncがあるremainder(dividingBy:)truncatingRemainder(dividingBy:)。あなたは、両方のためのドキュメントを読みたいと思うかもしれません。また、C ++のために同じ質問を参照してくださいstackoverflow.com/questions/6102948/...
Sulthan

2

以下がSwift 3で機能することがわかりました。

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

ここで、totalSecondsですTimeIntervalDouble)。


3
たとえばtotalSeconds = 59.8、コードが0分と0秒を計算する場合、床と丸みを混ぜることはお勧めできません。
マーティンR

はい、あなたが正しい。実際、これroundはまったく必要ありません。
benwiggy 2017

0

コードがより安全になると思わない限り、浮動小数点数用に別のモジュロ演算子を作成する必要はありません。次の%ように、演算子をオーバーロードして浮動小数点数を受け入れることができます。

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

使用法

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

%同じタイの任意の2つの浮動小数点数で使用できるようになりました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.