2014-11-25 56 views
18

我正在寻找一个直接的方式位转换位的Int值为UInt,反之亦然。例如(使用简单的8个整数)我要实现以下目标:INT到UInt(反之亦然)位在斯威夫特铸造

let unsigned: UInt8 = toUInt8(-1) // unsigned is 255 or 0xff 
let signed: Int8 = toInt8(0xff) // signed is -1 

起初,我想出了以下解决方案:

let unsigned = unsafeBitCast(Int8(-1), UInt8.self) 
let signed = unsafeBitCast(UInt8(0xff), Int8.self) 

但是,苹果在“unsafeBitCast() “文档声明如下:

..小心::打破了Swift类型系统的保证;极度小心使用 。几乎总是有更好的方法去做任何事情。

有没有人有更好的方法?

+0

类似的问题在这里:[将签名转换为无符号的Swift](http://stackoverflow.com/questions/25666846/converting-signed-to-unsigned-in-swift)。 – 2014-11-25 13:07:44

+0

@Martin是的,你是对的。我发誓我一直在谷歌和stackoveflow搜索这一点,它从来没有出现过。 – 2014-11-25 13:16:06

回答

32

你可以这样做:

let unsigned = UInt8(bitPattern: Int8(-1)) // -> 255 
let signed = Int8(bitPattern: UInt8(0xff)) // -> -1 

许多类似的初始化存在:

extension Int8 { 
    init(_ v: UInt8) 
    init(_ v: UInt16) 
    init(truncatingBitPattern: UInt16) 
    init(_ v: Int16) 
    init(truncatingBitPattern: Int16) 
    init(_ v: UInt32) 
    init(truncatingBitPattern: UInt32) 
    init(_ v: Int32) 
    init(truncatingBitPattern: Int32) 
    init(_ v: UInt64) 
    init(truncatingBitPattern: UInt64) 
    init(_ v: Int64) 
    init(truncatingBitPattern: Int64) 
    init(_ v: UInt) 
    init(truncatingBitPattern: UInt) 
    init(_ v: Int) 
    init(truncatingBitPattern: Int) 
    init(bitPattern: UInt8) 
} 
2

我拿了代数路线。测试一直很痛苦,因为打破执行的强打字很容易出现溢出,PlayGround从toUInt函数返回一个负值,它在执行双重投射时不断崩溃或出现有趣的错误(我打开了一个错误报告)。反正这是我结束了:

func toUint(signed: Int) -> UInt { 

    let unsigned = signed >= 0 ? 
     UInt(signed) : 
     UInt(signed - Int.min) + UInt(Int.max) + 1 

    return unsigned 
} 

func toInt(unsigned: UInt) -> Int { 

    let signed = (unsigned <= UInt(Int.max)) ? 
     Int(unsigned) : 
     Int(unsigned - UInt(Int.max) - 1) + Int.min 

    return signed 
} 

我所有的极端值(UInt.min,UInt.max,Int.min,Int.max)和测试他们的时候的XCode不会发疯似乎工作,但看起来过于复杂。够离奇UINT为INT位铸造可以用散列值财产只是实现为:

signed = UInt.max.hashValue // signed is -1 

但显然它不能保证总是工作(它应该,但我宁愿不走的机会) 。

任何其他的想法将不胜感激。

0

numericCast(...)是你在找什么。它是一组通用函数,可以将数据类型转换为不同的数字类型。它根据参数类型和返回类型选择正确的实现。

+0

与'UInt8(bitpattern:)'相比较,那么'numericFast'陷阱在/ overflow下,例如'let foo:UInt8 = numericCast(-1)'会崩溃。所以选择正确的取决于用例。 :) – 2016-09-01 09:50:56