Skip to content

Is power of two #358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Sep 30, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
// author(s) [red_byte](https://github.com/i-redbyte)
// see arithmeticmean_test.go

// Package binarymath describes algorithms that use binary operations for different calculations.
package binarymath
// Package binary describes algorithms that use binary operations for different calculations.
package binary

func MeanUsingAndXor(a int, b int) int {
return ((a ^ b) >> 1) + (a & b)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// author(s) [red_byte](https://github.com/i-redbyte)
// see arithmeticmean.go

package binarymath
package binary

import "testing"

Expand Down
36 changes: 36 additions & 0 deletions math/binary/checkisnumberpoweroftwo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// checkisnumberpoweroftwo.go
// description: Is the number a power of two
// details:
// Checks if a number is a power of two- [Power of two](https://en.wikipedia.org/wiki/Power_of_two)
// author(s) [red_byte](https://github.com/i-redbyte)
// see checkisnumberpoweroftwo_test.go

package binary

// IsPowerOfTwo This function uses the fact that powers of 2 are represented
// like 10...0 in binary, and numbers one less than the power of 2
// are represented like 11...1.
// Therefore, using the and function:
// 10...0
// & 01...1
// 00...0 -> 0
// This is also true for 0, which is not a power of 2, for which we
// have to add and extra condition.
func IsPowerOfTwo(x int) bool {
return x > 0 && (x&(x-1)) == 0
}

// IsPowerOfTwoLeftShift This function takes advantage of the fact that left shifting a number
// by 1 is equivalent to multiplying by 2. For example, binary 00000001 when shifted by 3 becomes 00001000,
// which in decimal system is 8 or = 2 * 2 * 2
func IsPowerOfTwoLeftShift(number uint) bool {
if number == 0 {
return false
}
for p := uint(1); p > 0; p = p << 1 {
if number == p {
return true
}
}
return false
}
93 changes: 93 additions & 0 deletions math/binary/checkisnumberpoweroftwo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// checkisnumberpoweroftwo_test.go
// description: Test for Is the number a power of two
// author(s) [red_byte](https://github.com/i-redbyte)
// see checkisnumberpoweroftwo.go

package binary

import (
math2 "github.com/TheAlgorithms/Go/math"
"math"
"testing"
)

func getTestsForPowerOfTwo() []struct {
name string
a int
missing bool
} {
var tests = []struct {
name string
a int
missing bool
}{
{"Is 64 a power of 2? - YES", 64, true},
{"Is 1 a power of 2? - YES", 1, true},
{"Is 2 a power of 2? - YES", 2, true},
{"Is 5 a power of 2? - NO", 5, false},
{"Is 1023 a power of 2? - NO", 1023, false},
{"Is 1024 a power of 2? - YES", 1024, true},
{"Is 0 a power of 2? - NO", 0, false},
{"Is 9223372036854775807 a power of 2? - NO", math.MaxInt64, false},
{"Is 9223372036854775806 a power of 2? - NO", math.MaxInt64, false},
{"Is 4611686018427387904 a power of 2? - YES", 4611686018427387904, true},
}
return tests
}

func TestIsPowerOfTwo(t *testing.T) {
tests := getTestsForPowerOfTwo()
for _, tv := range tests {
t.Run(tv.name, func(t *testing.T) {
result := IsPowerOfTwo(tv.a)
t.Log(tv.a, " ", result)
if result != tv.missing {
t.Errorf("Wrong result! Expected:%v, returned:%v ", tv.missing, result)
}
})
}
}

func TestIsPowerOfTwoLeftShift(t *testing.T) {
tests := getTestsForPowerOfTwo()
for _, tv := range tests {
t.Run(tv.name, func(t *testing.T) {
result := IsPowerOfTwoLeftShift(uint(tv.a))
t.Log(tv.a, " ", result)
if result != tv.missing {
t.Errorf("Wrong result! Expected:%v, returned:%v ", tv.missing, result)
}
})
}
}

func TestIsPowOfTwoUseLog(t *testing.T) {
tests := getTestsForPowerOfTwo()
for _, tv := range tests {
t.Run(tv.name, func(t *testing.T) {
result := math2.IsPowOfTwoUseLog(float64(tv.a))
t.Log(tv.a, " ", result)
if result != tv.missing {
t.Errorf("Wrong result! Expected:%v, returned:%v ", tv.missing, result)
}
})
}
}

func BenchmarkIsPowerOfTwoBinaryMethod(b *testing.B) {
for i := 0; i < b.N; i++ {
IsPowerOfTwo(1024)
}
}

func BenchmarkIsPowerOfTwoUseCycleAndLeftShift(b *testing.B) {
for i := 0; i < b.N; i++ {
IsPowerOfTwoLeftShift(1024)
}
}

func BenchmarkIsPowerOfTwoUseLog(b *testing.B) {
for i := 0; i < b.N; i++ {
math2.IsPowOfTwoUseLog(1024)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// author(s) [red_byte](https://github.com/i-redbyte)
// see xorsearch_test.go

package binarymath
package binary

func XorSearchMissingNumber(a []int) int {
n := len(a)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// description: Test for Find a missing number in a sequence
// author(s) [red_byte](https://github.com/i-redbyte)
// see xorsearch.go
package binarymath
package binary

import (
"testing"
Expand Down
16 changes: 16 additions & 0 deletions math/checkisnumberpoweroftwo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package math

import (
"math"
)

// IsPowOfTwoUseLog This function checks if a number is a power of two using the logarithm.
// The limiting degree can be from 0 to 63.
// See alternatives in the binary package.
func IsPowOfTwoUseLog(number float64) bool {
if number == 0 || math.Round(number) == math.MaxInt64 {
return false
}
log := math.Log2(number)
return log == math.Round(log)
}
54 changes: 54 additions & 0 deletions math/checkisnumberpoweroftwo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// checkisnumberpoweroftwo_test.go
// description: Test for Is the number a power of two
// author(s) [red_byte](https://github.com/i-redbyte)
// see checkisnumberpoweroftwo.go

package math

import (
"math"
"testing"
)

func getTestsForPowerOfTwo() []struct {
name string
a int
missing bool
} {
var tests = []struct {
name string
a int
missing bool
}{
{"Is 64 a power of 2? - YES", 64, true},
{"Is 1 a power of 2? - YES", 1, true},
{"Is 2 a power of 2? - YES", 2, true},
{"Is 5 a power of 2? - NO", 5, false},
{"Is 1023 a power of 2? - NO", 1023, false},
{"Is 1024 a power of 2? - YES", 1024, true},
{"Is 0 a power of 2? - NO", 0, false},
{"Is 9223372036854775807 a power of 2? - NO", math.MaxInt64, false},
{"Is 9223372036854775806 a power of 2? - NO", math.MaxInt64, false},
{"Is 4611686018427387904 a power of 2? - YES", 4611686018427387904, true},
}
return tests
}

func TestIsPowOfTwoUseLog(t *testing.T) {
tests := getTestsForPowerOfTwo()
for _, tv := range tests {
t.Run(tv.name, func(t *testing.T) {
result := IsPowOfTwoUseLog(float64(tv.a))
t.Log(tv.a, " ", result)
if result != tv.missing {
t.Errorf("Wrong result! Expected:%v, returned:%v ", tv.missing, result)
}
})
}
}

func BenchmarkIsPowerOfTwoUseLog(b *testing.B) {
for i := 0; i < b.N; i++ {
IsPowOfTwoUseLog(1024)
}
}