"%를 사용할 수 없음 : 대신 truncatingRemainder 사용"은 무엇을 의미합니까?


104

확장에 대한 코드를 사용할 때 다음 오류가 발생합니다. 다른 연산자를 사용하거나 인터넷 검색을 기반으로 표현식의 값을 수정하도록 요청하는지 확실하지 않습니다.

오류 : %를 사용할 수 없음 : 대신 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대신 방법 과 같은 것을 사용하는 것을 고려해야 합니다.
matt

1
당신은에 모듈로 사용할 수 Float64있지만에 Int단지; 따라서 let minutes:Int = Int(totalSeconds) % 3600 / 60; let seconds:Int = Int(totalSeconds) % 60올바른 방법입니다.
holex

답변:


174

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에서 값을 표시 하려는 방법에 따라 초 값을 추출하여 전달 NSDateFormatter하거나 NSDateComponentsFormatter적절한 로케일 지원을받는 것이 더 나을 수 있습니다 .


10

신속한 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)
}

이 간단한 신속한 3 마이그레이션 팁은 많은 통찰력 (35k loc / 8 일 마이그레이션)이 포함 된보다 포괄적 인 신속한 3 마이그레이션 가이드의 일부입니다. http://eon.codes/blog/2017/01/12/swift-3-migration /


1
이 A는 괜찮 흥미로운 정보를 제공하고, 또한 Q. 대답하려고
야쿱 Truhlář

3
@Jakub Truhlář ... 남자, Thx. IMO 이것은 내 최고의 신속한 3 마이그레이션 수정이었습니다. 사람들이 반대 투표를했다고 믿을 수 없습니다. 모듈로는 매우 중요한 개념이며 산술이있는 모든 코드북에서 생각됩니다. 코드의 산술은 가능한 한 간결하게 작성해야하므로 장황하게 만드는 것은 의미가 없습니다. 산술을 이해하는 우리의인지 능력은 개별 변수의 의미를 이해하는 것과는 반대로 완전한 그림을 볼 수있을 때 증가합니다. IMO 포괄적 인 변수 이름 지정은 비즈니스 로직에서 중요하지만 산술이 아니라 그 반대입니다.
eonist

2
@GitSync Modulo는 중요한 개념이지만 정수에만 존재합니다. 차이점을 이해해야합니다.
Sulthan

5
@GitSync 모듈로 연산은 정수에 대해서만 존재합니다. 나머지에 대해 이야기하고 있습니다. 소수 값에는 두 가지 유형의 나머지가 있습니다. 이것이 Swift가 작업을 명시 적으로 결정한 이유입니다. double 값에서 정수 나머지 ( truncating restder ) 를 계산하는 것은 그리 일반적이지 않습니다 .
Sulthan

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 초를 계산하기 때문입니다.
Martin R

네 말이 맞아. 실제로 round는 전혀 필요하지 않습니다.
benwiggy

1

코드를 더 안전하게 만든다고 생각하지 않는 한 부동 소수점 숫자에 대해 별도의 모듈로 연산자를 만들 필요가 없습니다. %연산자를 오버로드하여 다음과 같이 부동 소수점 숫자를 허용 할 수 있습니다 .

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

용법

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

이제 %동일한 유형의 두 부동 소수점 숫자를 사용할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.