web-dev-qa-db-ja.com

SwiftでのUIntへのビット(およびその逆)ビットキャスト

Intのビット値をUIntに、またはその逆にビットキャストする直接的な方法を探しています。たとえば、(簡単にするために8ビット整数を使用しています)次のことを実現したいと思います。

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)

しかし、Appleは次のように述べています:

..注意:: Swiftの型システムの保証を破ります。細心の注意を払って使用してください。ほとんどの場合、何かを行うためのより良い方法があります。

誰かがより良い方法を持っていますか?

23

できるよ:

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)
}
40
rintaro

私は代数のルートを取った。強力なタイピングによって実行が中断されてオーバーフローが発生しやすく、テストが面倒でした。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へのビットキャストは、次のようにhashvalueプロパティで簡単に実現できます。

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

しかし、それが常に機能することが保証されているわけではないことは明らかです(動作するはずですが、私はチャンスを逃したくありません)。

他のアイデアは高く評価されます。

3

numericCast(...)は、探しているものです。これは、さまざまな数値型との間で変換を行う一連の汎用関数です。引数のタイプと戻り値のタイプに基づいて、正しい実装を選択します。

1
stigi