首页 文章详情

特殊情况下,Go 中不同取模操作的效率比较

Go语言精选 | 574 2020-10-01 08:10 0 0 0
UniSMS (合一短信)
点击上方蓝色“Go语言中文网”关注,回复「电子书」领全套Go资料

所指代的特殊情况是指 a % b,b 为 2 的 n 次方的情况。

额(⊙﹏⊙),作为平时使用的话,完全用不上,在非常巨量的操作下才可能会有差距

  • 先拿 10 进制举例,如果 15648615341 % 10,那你肯定立马知道结果是 1,10 变成 100,你也知道结果是 41
  • 同样的换成二进制 1110100100101110101110101110101101 % 10 (二进制哦~),结果是 1(也就表示是奇数),换成 100 结果是 1,1000 ==>> 101
  • 所以得出结论 如果 a % b, b 是 2 的次方的时候(也就是可以表示为 1 << n 的数),结果就是 a 的后 n 位。后 n 位可以用 a % (b - 1) 的方式取出

下面是测试的代码,不足之处欢迎指正

package main

import (
 "math/rand"
 "testing"
 "time"
)

func BenchmarkModByAnd(b *testing.B) {
 // 忽略开头的初始化
 b.StopTimer()
 for i := range [100][0]int{} {
  // 随机种子
  rand.Seed(time.Now().Unix())

  // 操作数赋值
  a := rand.Intn(1000000)
  c := 1 << (i % 63)

  // 运算部分
  b.StartTimer()
  // 循环此处忽略不计,如果每次都放到内部消耗CPU,跑不出来
  for i := 0; i < b.N; i++ {
   _ = a & (c - 1)
  }
  b.StopTimer()

  // 结果验证,毕竟是特殊方法嘛
  res := a % c
  r := a & (c - 1)

  if r != res {
   b.Fail()
  }
 }
}
/*
goos: windows
goarch: amd64
BenchmarkModByAnd
BenchmarkModByAnd-12     44577350         25.7 ns/op
PASS

上为 goland 内部直接运行的测试结果
 */


func BenchmarkModNormally(b *testing.B) {
 b.StopTimer()
 for i := range [100][0]int{} {
  rand.Seed(time.Now().Unix())

  a := rand.Intn(1000000)
  c := 1 << (i % 63)

  b.StartTimer()
  for i := 0; i < b.N; i++ {
   _ = a % c
  }
  b.StopTimer()
 }
}
/*
goos: windows
goarch: amd64
BenchmarkModNormally
BenchmarkModNormally-12     23575406         50.8 ns/op
PASS

上为 goland 内部直接运行的测试结果
 */

可以看到位运算的效率和直接运算(%)的效率是两倍的关系

但是,如果没达到特别特别大的量级,是看不出区别的┭┮﹏┭┮,仅仅作为知识拓展吧

本文作者:lgf133214

原文链接:https://studygolang.com/articles/30919


推荐阅读


福利

我为大家整理了一份从入门到进阶的Go学习资料礼包(下图只是部分),同时还包含学习建议:入门看什么,进阶看什么。

关注公众号 「polarisxu」,回复 ebook 获取;还可以回复「进群」,和数万 Gopher 交流学习。


good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter