Skip to content

Commit 420ddd6

Browse files
i-redbytesiriak
andauthored
Add is power of two (#358)
* feat: is power of two algorithm * fix: add doc and rename files * fix: text for tests * fix: after review * fix: after review2 * fix: move IsPowerOfTwoUseLog method to math package * fix: rename IsPowerOfTwoUseLog * fix: create checkisnumberpoweroftwo_test Co-authored-by: Andrii Siriak <[email protected]>
1 parent a91ef21 commit 420ddd6

8 files changed

+204
-5
lines changed

math/binarymath/arithmeticmean.go renamed to math/binary/arithmeticmean.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
// author(s) [red_byte](https://github.com/i-redbyte)
66
// see arithmeticmean_test.go
77

8-
// Package binarymath describes algorithms that use binary operations for different calculations.
9-
package binarymath
8+
// Package binary describes algorithms that use binary operations for different calculations.
9+
package binary
1010

1111
func MeanUsingAndXor(a int, b int) int {
1212
return ((a ^ b) >> 1) + (a & b)

math/binarymath/arithmeticmean_test.go renamed to math/binary/arithmeticmean_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// author(s) [red_byte](https://github.com/i-redbyte)
44
// see arithmeticmean.go
55

6-
package binarymath
6+
package binary
77

88
import "testing"
99

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// checkisnumberpoweroftwo.go
2+
// description: Is the number a power of two
3+
// details:
4+
// Checks if a number is a power of two- [Power of two](https://en.wikipedia.org/wiki/Power_of_two)
5+
// author(s) [red_byte](https://github.com/i-redbyte)
6+
// see checkisnumberpoweroftwo_test.go
7+
8+
package binary
9+
10+
// IsPowerOfTwo This function uses the fact that powers of 2 are represented
11+
// like 10...0 in binary, and numbers one less than the power of 2
12+
// are represented like 11...1.
13+
// Therefore, using the and function:
14+
// 10...0
15+
// & 01...1
16+
// 00...0 -> 0
17+
// This is also true for 0, which is not a power of 2, for which we
18+
// have to add and extra condition.
19+
func IsPowerOfTwo(x int) bool {
20+
return x > 0 && (x&(x-1)) == 0
21+
}
22+
23+
// IsPowerOfTwoLeftShift This function takes advantage of the fact that left shifting a number
24+
// by 1 is equivalent to multiplying by 2. For example, binary 00000001 when shifted by 3 becomes 00001000,
25+
// which in decimal system is 8 or = 2 * 2 * 2
26+
func IsPowerOfTwoLeftShift(number uint) bool {
27+
if number == 0 {
28+
return false
29+
}
30+
for p := uint(1); p > 0; p = p << 1 {
31+
if number == p {
32+
return true
33+
}
34+
}
35+
return false
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// checkisnumberpoweroftwo_test.go
2+
// description: Test for Is the number a power of two
3+
// author(s) [red_byte](https://github.com/i-redbyte)
4+
// see checkisnumberpoweroftwo.go
5+
6+
package binary
7+
8+
import (
9+
math2 "github.com/TheAlgorithms/Go/math"
10+
"math"
11+
"testing"
12+
)
13+
14+
func getTestsForPowerOfTwo() []struct {
15+
name string
16+
a int
17+
missing bool
18+
} {
19+
var tests = []struct {
20+
name string
21+
a int
22+
missing bool
23+
}{
24+
{"Is 64 a power of 2? - YES", 64, true},
25+
{"Is 1 a power of 2? - YES", 1, true},
26+
{"Is 2 a power of 2? - YES", 2, true},
27+
{"Is 5 a power of 2? - NO", 5, false},
28+
{"Is 1023 a power of 2? - NO", 1023, false},
29+
{"Is 1024 a power of 2? - YES", 1024, true},
30+
{"Is 0 a power of 2? - NO", 0, false},
31+
{"Is 9223372036854775807 a power of 2? - NO", math.MaxInt64, false},
32+
{"Is 9223372036854775806 a power of 2? - NO", math.MaxInt64, false},
33+
{"Is 4611686018427387904 a power of 2? - YES", 4611686018427387904, true},
34+
}
35+
return tests
36+
}
37+
38+
func TestIsPowerOfTwo(t *testing.T) {
39+
tests := getTestsForPowerOfTwo()
40+
for _, tv := range tests {
41+
t.Run(tv.name, func(t *testing.T) {
42+
result := IsPowerOfTwo(tv.a)
43+
t.Log(tv.a, " ", result)
44+
if result != tv.missing {
45+
t.Errorf("Wrong result! Expected:%v, returned:%v ", tv.missing, result)
46+
}
47+
})
48+
}
49+
}
50+
51+
func TestIsPowerOfTwoLeftShift(t *testing.T) {
52+
tests := getTestsForPowerOfTwo()
53+
for _, tv := range tests {
54+
t.Run(tv.name, func(t *testing.T) {
55+
result := IsPowerOfTwoLeftShift(uint(tv.a))
56+
t.Log(tv.a, " ", result)
57+
if result != tv.missing {
58+
t.Errorf("Wrong result! Expected:%v, returned:%v ", tv.missing, result)
59+
}
60+
})
61+
}
62+
}
63+
64+
func TestIsPowOfTwoUseLog(t *testing.T) {
65+
tests := getTestsForPowerOfTwo()
66+
for _, tv := range tests {
67+
t.Run(tv.name, func(t *testing.T) {
68+
result := math2.IsPowOfTwoUseLog(float64(tv.a))
69+
t.Log(tv.a, " ", result)
70+
if result != tv.missing {
71+
t.Errorf("Wrong result! Expected:%v, returned:%v ", tv.missing, result)
72+
}
73+
})
74+
}
75+
}
76+
77+
func BenchmarkIsPowerOfTwoBinaryMethod(b *testing.B) {
78+
for i := 0; i < b.N; i++ {
79+
IsPowerOfTwo(1024)
80+
}
81+
}
82+
83+
func BenchmarkIsPowerOfTwoUseCycleAndLeftShift(b *testing.B) {
84+
for i := 0; i < b.N; i++ {
85+
IsPowerOfTwoLeftShift(1024)
86+
}
87+
}
88+
89+
func BenchmarkIsPowerOfTwoUseLog(b *testing.B) {
90+
for i := 0; i < b.N; i++ {
91+
math2.IsPowOfTwoUseLog(1024)
92+
}
93+
}

math/binarymath/xorsearch.go renamed to math/binary/xorsearch.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// author(s) [red_byte](https://github.com/i-redbyte)
66
// see xorsearch_test.go
77

8-
package binarymath
8+
package binary
99

1010
func XorSearchMissingNumber(a []int) int {
1111
n := len(a)

math/binarymath/xorsearch_test.go renamed to math/binary/xorsearch_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// description: Test for Find a missing number in a sequence
33
// author(s) [red_byte](https://github.com/i-redbyte)
44
// see xorsearch.go
5-
package binarymath
5+
package binary
66

77
import (
88
"testing"

math/checkisnumberpoweroftwo.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package math
2+
3+
import (
4+
"math"
5+
)
6+
7+
// IsPowOfTwoUseLog This function checks if a number is a power of two using the logarithm.
8+
// The limiting degree can be from 0 to 63.
9+
// See alternatives in the binary package.
10+
func IsPowOfTwoUseLog(number float64) bool {
11+
if number == 0 || math.Round(number) == math.MaxInt64 {
12+
return false
13+
}
14+
log := math.Log2(number)
15+
return log == math.Round(log)
16+
}

math/checkisnumberpoweroftwo_test.go

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// checkisnumberpoweroftwo_test.go
2+
// description: Test for Is the number a power of two
3+
// author(s) [red_byte](https://github.com/i-redbyte)
4+
// see checkisnumberpoweroftwo.go
5+
6+
package math
7+
8+
import (
9+
"math"
10+
"testing"
11+
)
12+
13+
func getTestsForPowerOfTwo() []struct {
14+
name string
15+
a int
16+
missing bool
17+
} {
18+
var tests = []struct {
19+
name string
20+
a int
21+
missing bool
22+
}{
23+
{"Is 64 a power of 2? - YES", 64, true},
24+
{"Is 1 a power of 2? - YES", 1, true},
25+
{"Is 2 a power of 2? - YES", 2, true},
26+
{"Is 5 a power of 2? - NO", 5, false},
27+
{"Is 1023 a power of 2? - NO", 1023, false},
28+
{"Is 1024 a power of 2? - YES", 1024, true},
29+
{"Is 0 a power of 2? - NO", 0, false},
30+
{"Is 9223372036854775807 a power of 2? - NO", math.MaxInt64, false},
31+
{"Is 9223372036854775806 a power of 2? - NO", math.MaxInt64, false},
32+
{"Is 4611686018427387904 a power of 2? - YES", 4611686018427387904, true},
33+
}
34+
return tests
35+
}
36+
37+
func TestIsPowOfTwoUseLog(t *testing.T) {
38+
tests := getTestsForPowerOfTwo()
39+
for _, tv := range tests {
40+
t.Run(tv.name, func(t *testing.T) {
41+
result := IsPowOfTwoUseLog(float64(tv.a))
42+
t.Log(tv.a, " ", result)
43+
if result != tv.missing {
44+
t.Errorf("Wrong result! Expected:%v, returned:%v ", tv.missing, result)
45+
}
46+
})
47+
}
48+
}
49+
50+
func BenchmarkIsPowerOfTwoUseLog(b *testing.B) {
51+
for i := 0; i < b.N; i++ {
52+
IsPowOfTwoUseLog(1024)
53+
}
54+
}

0 commit comments

Comments
 (0)