代码之家  ›  专栏  ›  技术社区  ›  Stéphane de Luca

对64位UInt右移位用作有符号移位感到困惑

  •  1
  • Stéphane de Luca  · 技术社区  · 8 年前

    为什么右移的行为如下?

    let a: UInt = 0x6177206d, b: UInt = 0x9e3779b1
    let m: UInt = a * b
    
    print("""
        let m = \(String(format:"%x", a)) * \(String(format:"%x", b)) = \(String(format:"%x", m))
    
        m>>4=\(String(format:"%x", m >> 4))
        m>>8=\(String(format:"%x", m >> 8))
        m>>16=\(String(format:"%x", m >> 16))
        m>>32=\(String(format:"%x", m >> 32))
        """)
    

    生产:

    let m = 6177206d * 9e3779b1 = ef1bf05d
    
    m>>4=fef1bf05
    m>>8=efef1bf0
    m>>16=a4efef1b
    m>>32=3c3ca4ef
    
    1 回复  |  直到 8 年前
        1
  •  0
  •   Rob Md Fahim Faez Abir    8 年前

    m ≠0xef1bf05d ; 它是 0x3c3ca4efef1bf05d .

    这个 %x 只处理32位值,而您正在处理64位值。使用 %lx String(m, radix: 16) 使用64位值:

    let a: UInt = 0x6177206d, b: UInt = 0x9e3779b1
    let m: UInt = a * b
    
    print("""
        let m = \(String(format:"%lx * %lx = %lx", a, b, m))
    
        m>>4  = \(String(format:"%lx", m >> 4))
        m>>8  = \(String(format:"%lx", m >> 8))
        m>>16 = \(String(format:"%lx", m >> 16))
        m>>32 = \(String(format:"%lx", m >> 32))
        """)
    

    或使用 %016lx 如果您想看到它的零填充(使其更容易看到过程中的移动),请:

    let m = 000000006177206d * 000000009e3779b1 = 3c3ca4efef1bf05d
    
    m>>4  = 03c3ca4efef1bf05
    m>>8  = 003c3ca4efef1bf0
    m>>16 = 00003c3ca4efef1b
    m>>32 = 000000003c3ca4ef