实验

实验 1

package main
 
import (
  "fmt"
  "math"
)
 
func main() {
  for i := -1; i > -5; i-- {
    v1 := div2(i)
    v2 := rightShift(i)
    mark := ""
    if v1 != v2 {
      mark = "!!!!!!"
    }
    fmt.Printf("[%d] 除法: %d; 右移: %d\t%s\n", i, v1, v2, mark)
  }
  fmt.Println()
 
  for i := -1; i > -5; i-- {
    v1 := times2(i)
    v2 := leftShift(i)
    mark := ""
    if v1 != v2 {
      mark = "!!!!!!"
    }
    fmt.Printf("[%d] 乘法: %d; 左移: %d\t%s\n", i, v1, v2, mark)
  }
  for i := math.MinInt/2 + 1; i < math.MinInt/2+6; i++ {
    v1 := times2(i)
    v2 := leftShift(i)
    mark := ""
    if v1 != v2 {
      mark = "!!!!!!"
    }
    fmt.Printf("[%d] 乘法: %d; 左移: %d\t%s\n", i, v1, v2, mark)
  }
  for i := math.MinInt; i < math.MinInt+5; i++ {
    v1 := times2(i)
    v2 := leftShift(i)
    mark := ""
    if v1 != v2 {
      mark = "!!!!!!"
    }
    fmt.Printf("[%d] 乘法: %d; 左移: %d\t%s\n", i, v1, v2, mark)
  }
}
 
func div2(a int) int {
  return a / 2
}
 
func rightShift(a int) int {
  return a >> 1
}
 
func times2(a int) int {
  return a * 2
}
 
func leftShift(a int) int {
  return a << 1
}

输出:

[-1] 除法: 0; 右移: -1  !!!!!!
[-2] 除法: -1; 右移: -1
[-3] 除法: -1; 右移: -2 !!!!!!
[-4] 除法: -2; 右移: -2
 
[-1] 乘法: -2; 左移: -2
[-2] 乘法: -4; 左移: -4
[-3] 乘法: -6; 左移: -6
[-4] 乘法: -8; 左移: -8
[-4611686018427387903] 乘法: -9223372036854775806; 左移: -9223372036854775806
[-4611686018427387902] 乘法: -9223372036854775804; 左移: -9223372036854775804
[-4611686018427387901] 乘法: -9223372036854775802; 左移: -9223372036854775802
[-4611686018427387900] 乘法: -9223372036854775800; 左移: -9223372036854775800
[-4611686018427387899] 乘法: -9223372036854775798; 左移: -9223372036854775798
[-9223372036854775808] 乘法: 0; 左移: 0
[-9223372036854775807] 乘法: 2; 左移: 2
[-9223372036854775806] 乘法: 4; 左移: 4
[-9223372036854775805] 乘法: 6; 左移: 6
[-9223372036854775804] 乘法: 8; 左移: 8

实验 2

package main
 
import (
  "fmt"
)
 
func main() {
  for i := -1; i > -9; i-- {
    v1 := div(i, 4)
    v2 := rightShift(i, 2)
    mark := ""
    if v1 != v2 {
      mark = "!!!!!!"
    }
    fmt.Printf("[%d] 除法: %d; 右移: %d\t%s\n", i, v1, v2, mark)
  }
}
 
func div(a, n int) int {
  return a / n
}
 
func rightShift(a, n int) int {
  return a >> n
}

输出:

[-1] 除法: 0; 右移: -1  !!!!!!
[-2] 除法: 0; 右移: -1  !!!!!!
[-3] 除法: 0; 右移: -1  !!!!!!
[-4] 除法: -1; 右移: -1
[-5] 除法: -1; 右移: -2 !!!!!!
[-6] 除法: -1; 右移: -2 !!!!!!
[-7] 除法: -1; 右移: -2 !!!!!!
[-8] 除法: -2; 右移: -2

实验 3

右移:向下取整

package main
 
import (
  "fmt"
  "math"
)
 
func main() {
  for i := -1; i > -999999; i-- {
    for j := 1; j <= 64; j++ {
      v1 := int(math.Floor(float64(i) / math.Pow(2, float64(j))))
      v2 := i >> j
      if v1 != v2 {
        fmt.Println("!!!!!!") // 没有打印
      }
    }
  }
}

实验 4

除法:向零取整

package main
 
import (
  "fmt"
  "math"
)
 
func main() {
  for i := -1; i > -999999; i-- {
    for j := 1; j <= 64; j++ {
      v1 := int(math.Ceil(float64(i) / math.Pow(2, float64(j))))
      v2 := i / int(math.Pow(2, float64(j)))
      if v1 != v2 {
        fmt.Println("!!!!!!") // 没有打印
      }
    }
  }
}

结论

  • 非负数
    • 可以用左移 n 位代替乘 2 的 n 次方
    • 可以用右移 n 位代替除以 2 的 n 次方
  • 负数
    • 可以用左移 n 位代替乘 2 的 n 次方
    • 不完全可以用右移 n 位代替除以 2 的 n 次方
      • a / n
        • a % n == 0 (整除):可以代替
        • a % n != 0(不整除):不可以代替
      • 本质:除法:向零取整;右移:向下取整