2016-12-17 8 views
3

SwiftのJavaの符号なし右シフト演算子と同等の機能をどのように実装しますか?Swiftの符号なし右シフト演算子 '>>>'

Java's documentationによれば、符号なし右シフト演算子「>>>」はゼロを左端にシフトし、「>>」の後の最も左の位置は符号拡張に依存する。

ので、例えば、

long s1 = (-7L >>> 16); // result is 281474976710655L 
    long s2 = (-7L >> 16); // result is -1 

スウィフトでこれを実現するために、私は何かなどを行うことによって符号ビットを除くすべてのビットを取ると、

let lsb = Int64.max + negativeNumber + 1 

お知らせナンバーこと否定的でなければなりません!シフト演算子をオーバーフローさせた場合、EXC_BAD_INSTRUCTIONによってアプリケーションがクラッシュします。これは非常にうまくありません。 また、Int64を目的に使用しています。より大きいデータ型がないので、(1 < < 63)のようなことを実行するとInt64がオーバーフローし、クラッシュします。だから、より大きなデータ型で((1 < < 63) - 1 +負の数)を書く代わりに、私はInt64.max + negativeNumber - 1として書きました。

そして、その正数を通常の論理シフトでシフトし、または符号の後の最初の左ビットの符号からのビット。

let shifted = (lsb >> bits) | 0x4000000000000000 

しかし、私に

((Int64.max - 7 + 1) >> 16) | 0x4000000000000000 // = 4611826755915743231 

ない私が間違ってやっているのかわからを期待される結果を与えるものではありません... また、この演算子に名前を付けることは可能であろう> >> 'とInt64を拡張?

編集:ここで以下OOperから溶液を添加 、

infix operator >>> : BitwiseShiftPrecedence 

func >>> (lhs: Int64, rhs: Int64) -> Int64 { 
    return Int64(bitPattern: UInt64(bitPattern: lhs) >> UInt64(rhs)) 
} 

Iはまた、32ビットに64ビットのint値を切り捨てることを含むスイフトでJavaランダムクラスを実装しました。 OOperのおかげで、私はtruncatingBitPattern初期化子を使ってオーバーフロー例外を避けることができたことに気付きました。関数は、「次」に記載されるようhereこのなりスウィフト、

var seed: Int64 = 0 
private func next(_ bits: Int32) -> Int32 { 
    seed = (seed &* 0x5DEECE66D &+ 0xB) & ((1 << 48) - 1) 
    let shifted : Int64 = seed >>> (48 - Int64(bits)) 
    return Int32(truncatingBitPattern: shifted) 
} 

答えて

4

一つの確実な方法は、符号なし整数型の符号なしシフト演算を使用している:

infix operator >>> : BitwiseShiftPrecedence 

func >>> (lhs: Int64, rhs: Int64) -> Int64 { 
    return Int64(bitPattern: UInt64(bitPattern: lhs) >> UInt64(rhs)) 
} 

print(-7 >>> 16) //->281474976710655 

(ビット数16とテストのため-7を使用すると、良い例ではないようです、それはすべての重要な失います16ビットの右シフトを伴うビット。)

あなたのやり方でそれをやりたいのであれば、ビット単位のOR欠落した符号ビットは定数0x4000000000000000になることはできません。ビット数== 0の場合、0x8000_0000_0000_0000(この定数はSwift Int64でオーバーフローします)、同じビットで論理的にシフトする必要があります。

だから、あなたはこのような何かを記述する必要があります。それはあなたが符号なしシフト操作を必要とする符号なし整数型で動作するようにはるかに容易に思える

infix operator >>>> : BitwiseShiftPrecedence 

func >>>> (lhs: Int64, rhs: Int64) -> Int64 { 
    if lhs >= 0 { 
     return lhs >> rhs 
    } else { 
     return (Int64.max + lhs + 1) >> rhs | (1 << (63-rhs)) 
    } 
} 

print(-7 >>>> 16) //->281474976710655 

+0

これは完璧です!ありがとう!また、切り捨て時にオーバーフローを避けるために、私はこれを初期化して使うことができます:Int32(truncatingBitPattern :)これを見ていたのは、Javaのドキュメントで指定されているJava Randomを実装していたからです。私は説明にそれを追加します。 – endavid

2

にスイフトは、符号なし整数型を有しているので、別々の符号なし右シフト演算の必要がありません。これは、署名されていない型を持たないことにしたがったJavaの選択肢です。

+0

これはまさにJavaが持つ問題を解決します。 Swiftには同じ問題がないため同等のものはありません。 – Alexander

0

この式は、私の作品:

((Int64.max - 7L + 1) >> 15) 

ませマスク、シフトを1ビット以下であること。

免責事項:Swiftでこれを確認することはできません。それを行うには