Reputation: 37581
Trying to call dispatch_time in Swift is doing my head in, here's why:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC), dispatch_get_main_queue(), {
doSomething()
})
Results in the error: "Could not find an overload for '*' that accepts the supplied arguments".
NSEC_PER_SEC is an UInt64 so time for some experiments:
let x:UInt64 = 1000
let m:Int64 = 10 * x
Results in the same error as above
let x:UInt64 = 1000
let m:Int64 = 10 * (Int64) x
Results in "Consecutive statements on a line must be separated by ';'"
let x:UInt64 = 1000
let m:Int64 = 10 * ((Int64) x)
Results in "Expected ',' separator"
let x:UInt64 = 1000
let m:Int64 = (Int64)10 * (Int64) x
Results in "Consecutive statements on a line must be separated by ';'"
Etc. etc.
Damn you Swift compiler, I give up. How do I cast a UInt64 to Int64, and/or how do you use dispatch_time in swift?
Upvotes: 10
Views: 18353
Reputation: 13750
To construct an Int64
using the bits of a UInt64
, use the init
seen here: https://developer.apple.com/reference/swift/int64/1538466-init
let myInt64 = Int64(bitPattern: myUInt64)
Upvotes: 8
Reputation: 668
simple solution for Swift 3 is an inbuilt function that takes care of overflows and buffer management.
var a:UInt64 = 1234567890
var b:Int64 = numericCast(a)
Upvotes: 0
Reputation: 4319
Casting a UInt64
to an Int64
is not safe since a UInt64
can have a number which is greater than Int64.max
, which will result in an overflow.
Here's a snippet for converting a UInt64
to Int64
and vice-versa:
// 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 }
}
}
This simply interprets the binary data of UInt64
as an Int64
, i.e. numbers greater than Int64.max
will be negative because of the sign bit at the most significat bit of the 64-bit integer.
If you just want positive integers, just get the absolute value.
EDIT: Depending on behavior, you can either get the absolute value, or:
if currentValue < 0 {
return Int64.max + currentValue + 1
} else {
return currentValue
}
The latter option is similar to stripping the sign bit. Ex:
// 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
Upvotes: 4
Reputation: 19
Better solution for converting:
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)));
}
Upvotes: 1
Reputation: 93276
You can "cast" between different integer types by initializing a new integer with the type you want:
let uint:UInt64 = 1234
let int:Int64 = Int64(uint)
It's probably not an issue in your particular case, but it's worth noting that different integer types have different ranges, and you can end up with out of range crashes if you try to convert between integers of different types:
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!
Each integer type has .max
and .min
class properties that you can use for checking ranges:
if (biggerUInt <= UInt64(Int64.max)) {
let biggerInt:Int64 = Int64(biggerUInt) // safe!
}
Upvotes: 7
Reputation: 22477
Try this:
let x:UInt64 = 1000 // 1,000
let m:Int64 = 10 * Int64(x) // 10,000
or even :
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)
It's not so much casting as initialising with a separate type...
Upvotes: 5