2014-11-25 57 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