124 votes

Que signifie "% est indisponible: utilisez plutôt truncatingRemainder"?

L'erreur suivante s'affiche lorsque j'utilise du code pour une extension. Je ne sais pas s'ils demandent simplement d'utiliser un autre opérateur ou de modifier les valeurs de l'expression en fonction d'une recherche Internet.

Erreur:% est indisponible: utilisez plutôt truncatingRemainder

Code d'extension:

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

La ou les erreurs se produisent lors de la définition des variables minutes et secondes.

195voto

Martin R Points 105727

CMTimeGetSeconds() retourne un nombre à virgule flottante (Float64aka Double). Dans Swift 2 on peut calculer la reste d'une division à virgule flottante

let rem = 2.5 % 1.1
print(rem) // 0.3

Dans Swift 3 c'est fait avec

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

Appliqué à votre code:

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

Toutefois, dans ce cas particulier, il est plus facile de convertir la durée pour un entier, en premier lieu:

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

Alors la prochaine lignes de simplifier à

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

27voto

rickster Points 19870

L' % module opérateur est défini uniquement pour les types d'entiers. Pour les types à virgule flottante, vous avez besoin pour être plus précis sur la nature de la norme IEEE 754 division/reste comportement que vous voulez, de sorte que vous devez appeler une méthode: soit remainder ou truncatingRemainder. (Si vous êtes en train de faire des mathématiques à virgule flottante vous avez réellement besoin de soins à ce sujet, et beaucoup d'autres choses, ou vous pouvez obtenir de l'inattendu et de mauvais résultats.)

Si vous avez réellement l'intention de faire integer module, vous avez besoin de convertir la valeur de retour de l' CMTimeGetSeconds pour un entier avant d'utiliser %. (Notez que si vous le faites, vous allez lop off les fractions de secondes... selon l'endroit où vous êtes en utilisant CMTime qui peut être important. Voulez-vous minutes:secondes:images, par exemple?)

Selon la façon dont vous souhaitez présenter, CMTime valeurs dans votre INTERFACE utilisateur, il peut être préférable d'extraire la valeur des secondes et de le transmettre NSDateFormatter ou NSDateComponentsFormatter de sorte que vous obtenir les paramètres régionaux de soutien.

10voto

eonist Points 1748

Ramener le simple modulo syntaxe dans swift 3:

Cette syntaxe a été fait suggéré sur les Pommes swift officiel liste de diffusion ici mais pour une raison quelconque, ils ont opté pour un moins élégant de la syntaxe.

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

Cette simple swift 3 migration de la pointe est un cadre plus global swift 3 guide de migration avec de nombreuses idées (35k loc / 8-jours de la migration) http://eon.codes/blog/2017/01/12/swift-3-migration/

2voto

benwiggy Points 288

J'ai trouvé que ce qui suit fonctionne dans Swift 3:

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

totalSeconds est un TimeInterval ( Double ).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X