Calculating large exponentiation in Golang - go

I've been trying to calculating 2^100 in Golang. I understand the limit of numeric type and tried using math/big package. Here's what I've tried but I can't figure out why it doesn't work.
I've used computation by powers of two method to calculate the exponentiation.
package main
import (
"fmt"
"math/big"
)
func main() {
two := big.NewInt(2)
hundred := big.NewInt(50)
fmt.Printf("2 ** 100 is %d\n", ExpByPowOfTwo(two, hundred))
}
func ExpByPowOfTwo(base, power *big.Int) *big.Int {
result := big.NewInt(1)
zero := big.NewInt(0)
for power != zero {
if modBy2(power) != zero {
multiply(result, base)
}
power = divideBy2(power)
base = multiply(base, base)
}
return result
}
func modBy2(x *big.Int) *big.Int {
return big.NewInt(0).Mod(x, big.NewInt(2))
}
func divideBy2(x *big.Int) *big.Int {
return big.NewInt(0).Div(x, big.NewInt(2))
}
func multiply(x, y *big.Int) *big.Int {
return big.NewInt(0).Mul(x, y)
}

BigInt package allows you to calculate x^y in log time (for some reason it is called exp). All you need is to pass nil as a last parameter.
package main
import (
"fmt"
"math/big"
)
func main() {
fmt.Println(new(big.Int).Exp(big.NewInt(5), big.NewInt(20), nil))
}
If you are interested how to calculate it by yourself, take a look at my implementation:
func powBig(a, n int) *big.Int{
tmp := big.NewInt(int64(a))
res := big.NewInt(1)
for n > 0 {
temp := new(big.Int)
if n % 2 == 1 {
temp.Mul(res, tmp)
res = temp
}
temp = new(big.Int)
temp.Mul(tmp, tmp)
tmp = temp
n /= 2
}
return res
}
or play with it on go playground.

For example,
package main
import (
"fmt"
"math/big"
)
func main() {
z := new(big.Int).Exp(big.NewInt(2), big.NewInt(100), nil)
fmt.Println(z)
}
Output:
1267650600228229401496703205376
Since it's a power of two, you could also do a bit shift:
package main
import (
"fmt"
"math/big"
)
func main() {
z := new(big.Int).Lsh(big.NewInt(1), 100)
fmt.Println(z)
}
Output:
1267650600228229401496703205376

You are returning immediately if power % 2 == 0. Instead, you just want to get the result of base ** (power /2). Then multiply result * result, and if power is even then multiply base to that.

To compute 2^100
package main
import (
"fmt"
"math/big"
)
func main() {
n := big.NewInt(0)
fmt.Println(n.SetBit(n, 100, 1))
}
Playground

package main
import(
"fmt"
"math/big"
)
func main() {
bigx, power10 := new(big.Int), new(big.Int)
var x int64
bigx.SetInt64(x) //set x int64 to bigx
power10.Exp(big.NewInt(10), bigx, nil) //power10 *big.Int points to solution
str10 := power10.Text(10)
fmt.Printf(str10) // print out the number and check for your self
}

Related

How to get the digits of int value in Golang

How can we get the digits of num := 658943 in Golang? I need to print each digit value from the given number (num) as integer instead of string.
package main
import "fmt"
func main() {
var (
num = 68932
digits []int
)
// do something with num, insert the result to digits
for _, val := range digits {
fmt.Println(val)
}
}
// expected output
// 6
// 8
// 9
// 3
// 2
You can use strconv
package main
import (
"fmt"
"strconv"
)
func main() {
var (
num = 68932
digits []int
)
s := strconv.Itoa(num)
for _, n := range s {
digits = append(digits, int(n-'0'))
}
for _, val := range digits {
fmt.Println(val)
}
}
https://go.dev/play/p/AHzwHPd7GJC

What Did I Miss in Input Process?

I am solving a problem in Hackerearth. Passed all the test cases except 1, showing "Time limit exceeded". What did I really miss in my code?
package main
import(
"fmt"
"strings"
)
func rotateRight(numbers []int, size int, k int) []int {
new_numbers := make([]int, size)
for index, value := range numbers {
new_numbers[(index + k) % size] = value
}
return new_numbers
}
func main() {
var test_case, size, k int
fmt.Scanf("%v", &test_case)
fmt.Scanln()
for i := 0; i < test_case; i++ {
fmt.Scanf("%v %v", &size, &k)
fmt.Scanln()
numbers := make([]int, size)
for i := 0; i<size; i++ {
fmt.Scanf("%v", &numbers[i])
}
result := rotateRight(numbers, size, k)
fmt.Println(strings.Trim(fmt.Sprint(result), "[]"))
}
}
maybe the reason is the way that you read the data, fmt is really slow, try change it with
package main
import (
"bufio"
"os"
)
func main() {
sc := bufio.NewScanner(os.Stdin)
sc.Scan()
sc.Text()//here you have your data
}
this change will improve the time wasted

How to get a factorial of 5000 in Go

I would like to calculate a factorial of 5000 in Go but got 0 as a result because the result is bigger than a uint64.
However, I was able to do it in Node.js by using
const BigNumber = require('big-number').
Is there an equivalent in Go?
What I did was:
func RecursiveFactorial(number int) big.Int {
if number >= 1 {
return big.Int{(number) * RecursiveFactorial(number-1)
} else {
return 1
}
}
In Go, use the math/big package.
For example,
// OEIS: A000142: Factorial numbers: n! = 1*2*3*4*...*n.
// https://oeis.org/A000045
package main
import (
"fmt"
"math/big"
)
func factorial(x *big.Int) *big.Int {
n := big.NewInt(1)
if x.Cmp(big.NewInt(0)) == 0 {
return n
}
return n.Mul(x, factorial(n.Sub(x, n)))
}
func main() {
fmt.Println(factorial(big.NewInt(5000)))
}
Playground: https://play.golang.org/p/53TmmygltkR
func factorial(n int64) *big.Int {
fac := new(big.Int)
fac.MulRange(1, n)
return fac
}
z.MulRange(a, b) from math/big computes the product from all int64 a to int64 b. It uses a split and recursiv algorithm (divide and conqueer). It's far more faster than school factorial algorithms. Compute 1 000 000! quickly = ~ 8.26393168833e+5565708
You need to use math/big package. You can implement computation recursively or iteratively. Iterative in most cases will be faster and produce less garbage. On my machine iterative impl works 3.1x faster and allocates 2.9x less garbage.
BenchmarkIterAndRecursive/recursive-6 3000 3891062 ns/op 17181056 B/op 15003 allocs/op
BenchmarkIterAndRecursive/iterative-6 10000 1237597 ns/op 656089 B/op 5172 allocs/op
package main
import (
"fmt"
"log"
"math/big"
"testing"
)
func main() {
fmt.Println(factorial(big.NewInt(5000)))
fmt.Println(factorialIter(5000))
}
func TestIterWorkTheSame(t *testing.T) {
recursive := factorial(big.NewInt(5000))
iterative := factorialIter(5000)
if recursive.Cmp(iterative) != 0 {
log.Fatalf("Invalid computation, \n[%v]\n[%v]", recursive, iterative)
}
}
func BenchmarkIterAndRecursive(b *testing.B) {
b.Run("recursive", func(b2 *testing.B) {
for i := 0; i < b2.N; i++ {
factorial(big.NewInt(5000))
}
})
b.Run("iterative", func(b2 *testing.B) {
for i := 0; i < b2.N; i++ {
factorialIter(5000)
}
})
}
func factorial(x *big.Int) *big.Int {
n := big.NewInt(1)
if x.Cmp(big.NewInt(0)) == 0 {
return n
}
return n.Mul(x, factorial(n.Sub(x, n)))
}
func factorialIter(x int) *big.Int {
result := big.NewInt(1)
for i := 2; i <= x; i++ {
result.Mul(result, big.NewInt(int64(i)))
}
return result
}

big int giving me wrong results in equality

For some reason I'm getting the wrong result from big int when I test the equality even though the mod result is actually correct!
For example, I would like to calculate 2015%2 which results in 1.
When I use big int, I get false when I do this:
fmt.Println((test.Mod(big.NewInt(2015),big.NewInt(2)))==big.NewInt(1))
However, when I use regular int, I get true (which is the correct thing anyway):
fmt.Println(2015%2==1)
Am I supposed to do the equality differently when using big int?
Package big
import "math/big"
func NewInt
func NewInt(x int64) *Int
NewInt allocates and returns a new Int set to x.
func (*Int) Cmp
func (x *Int) Cmp(y *Int) (r int)
Cmp compares x and y and returns:
-1 if x < y
0 if x == y
+1 if x > y
The variables a and b are pointers: *big.Int. Use the Cmp method to compare values. For example,
package main
import (
"fmt"
"math/big"
)
func main() {
a := big.NewInt(42)
fmt.Printf("a: %[1]T %[1]p %[1]v\n", a)
b := big.NewInt(42)
fmt.Printf("b: %[1]T %[1]p %[1]v\n", b)
fmt.Println("pointers:", a == b) // compare pointers
fmt.Println("values: ", a.Cmp(b) == 0) // compare values
fmt.Println()
test := new(big.Int)
fmt.Println((test.Mod(big.NewInt(2015), big.NewInt(2))).Cmp(big.NewInt(1)) == 0)
}
Playground: https://play.golang.org/p/TH6UzceZ4y
Output:
a: *big.Int 0x1040a0c0 42
b: *big.Int 0x1040a0d0 42
pointers: false
values: true
true
Have a look at the (*int)Cmp function.
package main
import (
"fmt"
"math/big"
)
func main() {
a := big.NewInt(5)
b := big.NewInt(5)
fmt.Println(a == b)
fmt.Println(a.Cmp(b))
}

Go big.Int factorial with recursion

I am trying to implement this bit of code:
func factorial(x int) (result int) {
if x == 0 {
result = 1;
} else {
result = x * factorial(x - 1);
}
return;
}
as a big.Int so as to make it effective for larger values of x.
The following is returning a value of 0 for fmt.Println(factorial(r))
The factorial of 7 should be 5040?
Any ideas on what I am doing wrong?
package main
import "fmt"
import "math/big"
func main() {
fmt.Println("Hello, playground")
//n := big.NewInt(40)
r := big.NewInt(7)
fmt.Println(factorial(r))
}
func factorial(n *big.Int) (result *big.Int) {
//fmt.Println("n = ", n)
b := big.NewInt(0)
c := big.NewInt(1)
if n.Cmp(b) == -1 {
result = big.NewInt(1)
}
if n.Cmp(b) == 0 {
result = big.NewInt(1)
} else {
// return n * factorial(n - 1);
fmt.Println("n = ", n)
result = n.Mul(n, factorial(n.Sub(n, c)))
}
return result
}
This code on go playground: http://play.golang.org/p/yNlioSdxi4
Go package math.big has func (*Int) MulRange(a, b int64). When called with the first parameter set to 1, it will return b!:
package main
import (
"fmt"
"math/big"
)
func main() {
x := new(big.Int)
x.MulRange(1, 10)
fmt.Println(x)
}
Will produce
3628800
In your int version, every int is distinct. But in your big.Int version, you're actually sharing big.Int values. So when you say
result = n.Mul(n, factorial(n.Sub(n, c)))
The expression n.Sub(n, c) actually stores 0 back into n, so when n.Mul(n, ...) is evaluated, you're basically doing 0 * 1 and you get back 0 as a result.
Remember, the results of big.Int operations don't just return their value, they also store them into the receiver. This is why you see repetition in expressions like n.Mul(n, c), e.g. why it takes n again as the first parameter. Because you could also sayresult.Mul(n, c) and you'd get the same value back, but it would be stored in result instead of n.
Here is your code rewritten to avoid this problem:
func factorial(n *big.Int) (result *big.Int) {
//fmt.Println("n = ", n)
b := big.NewInt(0)
c := big.NewInt(1)
if n.Cmp(b) == -1 {
result = big.NewInt(1)
}
if n.Cmp(b) == 0 {
result = big.NewInt(1)
} else {
// return n * factorial(n - 1);
fmt.Println("n = ", n)
result = new(big.Int)
result.Set(n)
result.Mul(result, factorial(n.Sub(n, c)))
}
return
}
And here is a slightly more cleaned-up/optimized version (I tried to remove extraneous allocations of big.Ints): http://play.golang.org/p/feacvk4P4O
For example,
package main
import (
"fmt"
"math/big"
)
func factorial(x *big.Int) *big.Int {
n := big.NewInt(1)
if x.Cmp(big.NewInt(0)) == 0 {
return n
}
return n.Mul(x, factorial(n.Sub(x, n)))
}
func main() {
r := big.NewInt(7)
fmt.Println(factorial(r))
}
Output:
5040
Non-recursive version:
func FactorialBig(n uint64) (r *big.Int) {
//fmt.Println("n = ", n)
one, bn := big.NewInt(1), new(big.Int).SetUint64(n)
r = big.NewInt(1)
if bn.Cmp(one) <= 0 {
return
}
for i := big.NewInt(2); i.Cmp(bn) <= 0; i.Add(i, one) {
r.Mul(r, i)
}
return
}
playground

Resources