Как вы приведете UInt64 к Int64?
Попытка вызвать dispatch_time в Swift делает мою голову, вот почему:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC), dispatch_get_main_queue(), {
doSomething()
})
В результате возникает ошибка: "Не удалось найти перегрузку для" * ", которая принимает предоставленные аргументы".
NSEC_PER_SEC - это UInt64, поэтому время для некоторых экспериментов:
let x:UInt64 = 1000
let m:Int64 = 10 * x
Результаты в той же ошибке, что и выше
let x:UInt64 = 1000
let m:Int64 = 10 * (Int64) x
Результаты в "Последовательных утверждениях в строке должны быть разделены знаком"; "
let x:UInt64 = 1000
let m:Int64 = 10 * ((Int64) x)
Результаты в "Ожидаемый", "разделитель"
let x:UInt64 = 1000
let m:Int64 = (Int64)10 * (Int64) x
Результаты в "Последовательных утверждениях в строке должны быть разделены знаком"; "
И т. Д.
Будь ты проклят компилятор Swift, я сдаюсь. Как преобразовать UInt64 в Int64 и / или как вы используете dispatch_time в swift?
6 ответов
Кастинг UInt64
для Int64
не безопасно, так как UInt64
может иметь число больше Int64.max
, что приведет к переполнению.
Вот фрагмент для преобразования UInt64
в Int64
и наоборот:
// Extension for 64-bit integer signed <-> unsigned conversion
extension Int64 {
var unsigned: UInt64 {
let valuePointer = UnsafeMutablePointer<Int64>.allocate(capacity: 1)
defer {
valuePointer.deallocate(capacity: 1)
}
valuePointer.pointee = self
return valuePointer.withMemoryRebound(to: UInt64.self, capacity: 1) { $0.pointee }
}
}
extension UInt64 {
var signed: Int64 {
let valuePointer = UnsafeMutablePointer<UInt64>.allocate(capacity: 1)
defer {
valuePointer.deallocate(capacity: 1)
}
valuePointer.pointee = self
return valuePointer.withMemoryRebound(to: Int64.self, capacity: 1) { $0.pointee }
}
}
Это просто интерпретирует двоичные данные UInt64
как Int64
то есть числа больше чем Int64.max
будет отрицательным из-за знакового бита в самом значимом бите 64-битного целого числа.
Если вам нужны только натуральные числа, просто получите абсолютное значение.
РЕДАКТИРОВАТЬ: В зависимости от поведения, вы можете получить абсолютное значение, или:
if currentValue < 0 {
return Int64.max + currentValue + 1
} else {
return currentValue
}
Последний вариант аналогичен удалению знака. Пример:
// Using an 8-bit integer for simplicity
// currentValue
0b1111_1111 // If this is interpreted as Int8, this is -1.
// Strip sign bit
0b0111_1111 // As Int8, this is 127. To get this we can add Int8.max
// Int8.max + currentValue + 1
127 + (-1) + 1 = 127
Чтобы построить Int64
используя биты UInt64
, использовать init
видел здесь: https://developer.apple.com/reference/swift/int64/1538466-init
let myInt64 = Int64(bitPattern: myUInt64)
Вы можете "приводить" между различными целочисленными типами, инициализируя новое целое число нужным вам типом:
let uint:UInt64 = 1234
let int:Int64 = Int64(uint)
Это, вероятно, не проблема в вашем конкретном случае, но стоит отметить, что разные целочисленные типы имеют разные диапазоны, и вы можете получить сбой вне диапазона, если попытаетесь конвертировать между целыми числами разных типов:
let bigUInt:UInt64 = UInt64(Int64.max) - 1 // 9,223,372,036,854,775,806
let bigInt:Int64 = Int64(bigUInt) // no problem
let biggerUInt:UInt64 = UInt64(Int64.max) + 1 // 9,223,372,036,854,775,808
let biggerInt:Int64 = Int64(biggerUInt) // crash!
Каждый целочисленный тип имеет .max
а также .min
Свойства класса, которые вы можете использовать для проверки диапазонов:
if (biggerUInt <= UInt64(Int64.max)) {
let biggerInt:Int64 = Int64(biggerUInt) // safe!
}
Попробуй это:
let x:UInt64 = 1000 // 1,000
let m:Int64 = 10 * Int64(x) // 10,000
или даже:
let x:UInt64 = 1000 // 1,000
let m = 10 * Int64(x) // 10,000
let n = Int64(10 * x) // 10,000
let y = Int64(x) // 1,000, as Int64 (as per @Bill's question)
Это не столько кастинг, сколько инициализация отдельным типом...
Лучшее решение для конвертации:
UInt64 Int64_2_UInt64(Int64 Value)
{
return (((UInt64)((UInt32)((UInt64)Value >> 32))) << 32)
| (UInt64)((UInt32)((UInt64)Value & 0x0ffffffff));
}
Int64 UInt64_2_Int64(UInt64 Value)
{
return (Int64)((((Int64)(UInt32)((UInt64)Value >> 32)) << 32)
| (Int64)((UInt32)((UInt64)Value & 0x0ffffffff)));
}
Простое решение для Swift 3 - это встроенная функция, которая заботится о переполнениях и управлении буфером.
var a:UInt64 = 1234567890
var b:Int64 = numericCast(a)