Skip to content

Commit 1fb424c

Browse files
authored
Add powers in terms of logarithms (TheAlgorithms#348)
1 parent 4edb802 commit 1fb424c

File tree

4 files changed

+177
-0
lines changed

4 files changed

+177
-0
lines changed

math/pi/spigotpi.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// spigotpi.go
2+
// description: A Spigot Algorithm for the Digits of Pi
3+
// details:
4+
// implementation of Spigot Algorithm for the Digits of Pi - [Spigot algorithm](https://en.wikipedia.org/wiki/Spigot_algorithm)
5+
// author(s) [red_byte](https://github.com/i-redbyte)
6+
// see spigotpi_test.go
7+
8+
package pi
9+
10+
import "strconv"
11+
12+
func Spigot(n int) string {
13+
pi := ""
14+
boxes := n * 10 / 3
15+
remainders := make([]int, boxes)
16+
for i := 0; i < boxes; i++ {
17+
remainders[i] = 2
18+
}
19+
digitsHeld := 0
20+
for i := 0; i < n; i++ {
21+
carriedOver := 0
22+
sum := 0
23+
for j := boxes - 1; j >= 0; j-- {
24+
remainders[j] *= 10
25+
sum = remainders[j] + carriedOver
26+
quotient := sum / (j*2 + 1)
27+
remainders[j] = sum % (j*2 + 1)
28+
carriedOver = quotient * j
29+
}
30+
remainders[0] = sum % 10
31+
q := sum / 10
32+
switch q {
33+
case 9:
34+
digitsHeld++
35+
case 10:
36+
q = 0
37+
for k := 1; k <= digitsHeld; k++ {
38+
replaced, _ := strconv.Atoi(pi[i-k : i-k+1])
39+
if replaced == 9 {
40+
replaced = 0
41+
} else {
42+
replaced++
43+
}
44+
pi = delChar(pi, i-k)
45+
pi = pi[:i-k] + strconv.Itoa(replaced) + pi[i-k:]
46+
}
47+
digitsHeld = 1
48+
default:
49+
digitsHeld = 1
50+
}
51+
pi += strconv.Itoa(q)
52+
}
53+
return pi
54+
}
55+
56+
func delChar(s string, index int) string {
57+
tmp := []rune(s)
58+
return string(append(tmp[0:index], tmp[index+1:]...))
59+
}

math/pi/spigotpi_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// spigotpi_test.go
2+
// description: Test for Spigot Algorithm for the Digits of Pi
3+
// author(s) [red_byte](https://github.com/i-redbyte)
4+
// see spigotpi.go
5+
package pi
6+
7+
import (
8+
"strconv"
9+
"testing"
10+
)
11+
12+
func TestSpigot(t *testing.T) {
13+
var tests = []struct {
14+
result string
15+
n int
16+
}{
17+
{"314159", 6},
18+
{"31415926535", 11},
19+
{"314159265358", 12},
20+
{"314159265358979323846", 21},
21+
{"314", 3},
22+
{"31415", 5},
23+
}
24+
for _, tv := range tests {
25+
t.Run(strconv.Itoa(tv.n)+":"+tv.result, func(t *testing.T) {
26+
result := Spigot(tv.n)
27+
if result != tv.result {
28+
t.Errorf("Bad result %d:%s", tv.n, tv.result)
29+
}
30+
})
31+
}
32+
}
33+
34+
func BenchmarkPiSpigotN10(b *testing.B) {
35+
for i := 0; i < b.N; i++ {
36+
Spigot(10)
37+
}
38+
}
39+
40+
func BenchmarkPiSpigotN100(b *testing.B) {
41+
for i := 0; i < b.N; i++ {
42+
Spigot(100)
43+
}
44+
}
45+
46+
func BenchmarkPiSpigotN1000(b *testing.B) {
47+
for i := 0; i < b.N; i++ {
48+
Spigot(1000)
49+
}
50+
}

math/power/powvialogarithm.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// powvialogarithm.go
2+
// description: Powers in terms of logarithms
3+
// details:
4+
// implementation of exponentiation using exponent and logarithm, without using loops - [Powers via logarithms wiki](https://en.wikipedia.org/wiki/Exponentiation#Powers_via_logarithms)
5+
// author(s) [red_byte](https://github.com/i-redbyte)
6+
// see powvialogarithm_test.go
7+
8+
package power
9+
10+
import (
11+
"math"
12+
)
13+
14+
func UsingLog(a float64, b float64) float64 {
15+
var p float64
16+
p = 1
17+
if a < 0 && int(b)&1 != 0 {
18+
p = -1
19+
}
20+
log := math.Log(math.Abs(a))
21+
exp := math.Exp(b * log)
22+
result := exp * p
23+
return math.Round(result)
24+
}

math/power/powvialogarithm_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// powvialogarithm_test.go
2+
// description: Test for UsingLog
3+
// author(s) [red_byte](https://github.com/i-redbyte)
4+
// see powvialogarithm.go
5+
6+
package power
7+
8+
import "testing"
9+
10+
func TestUsingLog(t *testing.T) {
11+
var tests = []struct {
12+
name string
13+
base float64
14+
power float64
15+
expected float64
16+
}{
17+
{"0^0", 99, 1, 99},
18+
{"-3^9", -3, 9, -19683},
19+
{"0^2", 0, 2, 0},
20+
{"2^0", 2, 0, 1},
21+
{"2^3", 2, 3, 8},
22+
{"8^3", 8, 3, 512},
23+
{"11^11", 11, 11, 285311670611},
24+
{"5^5", 5, 5, 3125},
25+
{"-7^2", -7, 2, 49},
26+
{"-6^3", -6, 3, -216},
27+
}
28+
29+
for _, tc := range tests {
30+
t.Run(tc.name, func(t *testing.T) {
31+
result := UsingLog(tc.base, tc.power)
32+
t.Log(result)
33+
if result != tc.expected {
34+
t.Errorf("Expected %.2f to the power of %.2f to be: %.2f, but got: %.2f", tc.base, tc.power, tc.expected, result)
35+
}
36+
})
37+
}
38+
}
39+
40+
func BenchmarkUsingLog(b *testing.B) {
41+
for i := 0; i < b.N; i++ {
42+
UsingLog(10, 5)
43+
}
44+
}

0 commit comments

Comments
 (0)