How do you do UInt64 for Int64?

Trying to call dispatch_time in Swift makes my head, here's why:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC), dispatch_get_main_queue(), { doSomething() }) 

Error result: "Could not find an overload for" * "that takes the provided arguments."

NSEC_PER_SEC is UInt64, so the time for some experiments is:

 let x:UInt64 = 1000 let m:Int64 = 10 * x 

Results with 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 a character"; "

 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 a character"; "

Etc. etc.

Damn you, Swift compiler, I give up. How do I enable UInt64 in Int64 and / or how do you use dispatch_time in swift?

+6
source share
6 answers

Passing UInt64 to Int64 unsafe because UInt64 may have a number greater than Int64.max , which will lead to overflow.

Here's a snippet for converting 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 UInt64 binary data as Int64 , i.e. numbers greater than Int64.max will be negative due to the sign bit in the most significant bit of the 64-bit integer.

If you need only positive integers, just get the absolute value.

EDIT: Depending on the 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 deleting a character descriptor. Example:

 // 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 
+2
source

Try the following:

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

This is not so much casting as initialization by a separate type ...

+5
source

You can "distinguish" between different integer types by initializing a new integer with the desired type:

 let uint:UInt64 = 1234 let int:Int64 = Int64(uint) 

This is probably not a problem in your particular case, but it is worth noting that different integer types have different ranges, and you may encounter errors outside the range if you try to convert 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 properties of the .min and .min , which can be used to check ranges:

 if (biggerUInt <= UInt64(Int64.max)) { let biggerInt:Int64 = Int64(biggerUInt) // safe! } 
+4
source

Best conversion solution:

 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))); } 
+1
source

To build Int64 using a UInt64 bits, use init here: https://developer.apple.com/reference/swift/int64/1538466-init

 let myInt64 = Int64(bitPattern: myUInt64) 
+1
source

A simple solution for Swift 3 is a built-in function that takes care of overflows and buffer management.

 var a:UInt64 = 1234567890 var b:Int64 = numericCast(a) 
0
source

Source: https://habr.com/ru/post/971669/


All Articles