golang operator % not defined on float64 - go

There's a leetcode test 326. Power of Three with a Mathematics method with java:
public class Solution {
public boolean isPowerOfThree(int n) {
return (Math.log(n) / Math.log(3) + epsilon) % 1 <= 2 * epsilon;
}
}
When I intend to convert this solution to Golang Like
import "math"
func isPowerOfThree(n int) bool {
return (math.Log10(float64(n)) / math.Log10(3)) % 1 == 0.0
}
then here comes the compile error like
Line 4: Char 53: invalid operation: math.Log10(float64(n)) / math.Log10(3) % 1 (operator % not defined on float64) (solution.go)
I check the math package but there's no supported function like % operator, Is there any valid operator like % in Golang? thanks a lot :)

TLDR: _, frac := math.Modf(f)
You could use func Mod(x, y float64) float64 in math package.
package main
import (
"math"
)
func isPowerOfThree(n int) bool {
return math.Mod((math.Log10(float64(n)) / math.Log10(3)), 1.0) == 0.0
}
You could also use func Modf(f float64) (int float64, frac float64).
package main
import (
"math"
)
func isPowerOfThree(n int) bool {
_, frac := math.Modf((math.Log10(float64(n)) / math.Log10(3)))
return frac == 0.0
}

We can not use just below function, as there can be more than one digit after decimal in frac
_, frac := math.Modf((math.Log10(float64(n)) / math.Log10(3)))
return frac == 0.0
So to resolve this, use below logic
func isPowerOfThree(n int) bool {
quo,_ := math.Modf((math.Log10(float64(n)) / math.Log10(3)))
return n == int(math.Pow(3, quo))
}

Related

golang return function and assigned value

I am going to learn 'golang return function' but I'm seriously confused.
why this code return "7" ?
how the value is assigned to "y" ?
package main
import "fmt"
func maked(x float64) func(float64) float64 {
fn := func(y float64) float64 {
return x - y
}
return fn
}
func main() {
test := maked(12)
fmt.Println(test(5))
// printed 7
}
test := maked(12) returns a function like below.
fn := func(y float64) float64 {
return 12 - y
}
and now test have that function. So test(5) runs above function with y = 5.
so 12 - 5 = 7

Condition validation in for loop

my below code to get square root works fine
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(Sqrt(9))
}
func Sqrt(x float64) float64 {
v := float64(1)
p := float64(0)
for {
p = v
v -= (v*v - x) / (2 * v)
fmt.Println(toFixed(p, 5), toFixed(v, 5))
if toFixed(p, 5) == toFixed(v, 5) {
break
}
}
return v
}
func toFixed(num float64, precision int) float64 {
output := math.Pow(10, float64(precision))
return float64(round(num*output)) / output
}
func round(num float64) int {
return int(num + math.Copysign(0.5, num))
}
but if I change the for loop in Sqrt function and remove if break from the loop like below then control flow do not get into for loop and Sqrt() function quits with value as 1.
for toFixed(p, 5) == toFixed(v, 5) {
p = v
v -= (v*v - x) / (2 * v)
fmt.Println(toFixed(p, 5), toFixed(v, 5))
}
Can you please suggest issue in above code?
Thanks
You should be checking for inequality != in your for condition.
I modified your code and it seems to be working fine now:
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(Sqrt(9))
}
func Sqrt(x float64) float64 {
v := float64(1)
p := float64(0)
for toFixed(p, 5) != toFixed(v, 5) {
p = v
v -= (v*v - x) / (2 * v)
}
return v
}
func toFixed(num float64, precision int) float64 {
output := math.Pow(10, float64(precision))
return float64(round(num*output)) / output
}
func round(num float64) int {
return int(num + math.Copysign(0.5, num))
}

How to convert int to bigint in golang?

I'm trying to implement fast double Fibonacci algorithm as described here:
// Fast doubling Fibonacci algorithm
package main
import "fmt"
// (Public) Returns F(n).
func fibonacci(n int) int {
if n < 0 {
panic("Negative arguments not implemented")
}
fst, _ := fib(n)
return fst
}
// (Private) Returns the tuple (F(n), F(n+1)).
func fib(n int) (int, int) {
if n == 0 {
return 0, 1
}
a, b := fib(n / 2)
c := a * (b*2 - a)
d := a*a + b*b
if n%2 == 0 {
return c, d
} else {
return d, c + d
}
}
func main() {
fmt.Println(fibonacci(13))
fmt.Println(fibonacci(14))
}
This works fine for small numbers; however, when the input number get larger, the program returns a wrong result. So I tried to use bigInt from math/big package:
// Fast doubling Fibonacci algorithm
package main
import (
"fmt"
"math/big"
)
// (Public) Returns F(n).
func fibonacci(n int) big.Int {
if n < 0 {
panic("Negative arguments not implemented")
}
fst, _ := fib(n)
return fst
}
// (Private) Returns the tuple (F(n), F(n+1)).
func fib(n int) (big.Int, big.Int) {
if n == 0 {
return big.Int(0), big.Int(1)
}
a, b := fib(n / 2)
c := a * (b*2 - a)
d := a*a + b*b
if n%2 == 0 {
return c, d
} else {
return d, c + d
}
}
func main() {
fmt.Println(fibonacci(123))
fmt.Println(fibonacci(124))
}
However, go build complains that
cannot convert 0 (type int) to type big.Int
How to mitigate this problem?
Use big.NewInt() instead of big.Int(). big.Int() is just type casting.
You need to check out documentation of big package
You should mostly use methods with form func (z *T) Binary(x, y *T) *T // z = x op y
To multiply 2 arguments you need to provide result variable, after it call Mul method. So, for example, to get result of 2*2 you need to:
big.NewInt(0).Mul(big.NewInt(2), big.NewInt(2))
You can try working example on the Go playground
Also you can create extension functions like:
func Mul(x, y *big.Int) *big.Int {
return big.NewInt(0).Mul(x, y)
}
To make code more readable:
// Fast doubling Fibonacci algorithm
package main
import (
"fmt"
"math/big"
)
// (Public) Returns F(n).
func fibonacci(n int) *big.Int {
if n < 0 {
panic("Negative arguments not implemented")
}
fst, _ := fib(n)
return fst
}
// (Private) Returns the tuple (F(n), F(n+1)).
func fib(n int) (*big.Int, *big.Int) {
if n == 0 {
return big.NewInt(0), big.NewInt(1)
}
a, b := fib(n / 2)
c := Mul(a, Sub(Mul(b, big.NewInt(2)), a))
d := Add(Mul(a, a), Mul(b, b))
if n%2 == 0 {
return c, d
} else {
return d, Add(c, d)
}
}
func main() {
fmt.Println(fibonacci(123))
fmt.Println(fibonacci(124))
}
func Mul(x, y *big.Int) *big.Int {
return big.NewInt(0).Mul(x, y)
}
func Sub(x, y *big.Int) *big.Int {
return big.NewInt(0).Sub(x, y)
}
func Add(x, y *big.Int) *big.Int {
return big.NewInt(0).Add(x, y)
}
Try it on the Go playground

How to convert float to complex?

With the very simple code :
package main
import (
"fmt"
"math"
"math/cmplx"
)
func sqrt(x float64) string {
if x < 0 {
return fmt.Sprint(cmplx.Sqrt(complex128(x)))
}
return fmt.Sprint(math.Sqrt(x))
}
func main() {
fmt.Println(sqrt(2), sqrt(-4))
}
I get the following error message :
main.go:11: cannot convert x (type float64) to type complex128
I tried different ways, but couldn't find out how to convert a float64 to complex128 (just to be able to use cmplx.Sqrt() function on a negative number).
Which is the correct way to handle this ?
You don't really want to convert a float64 to complex128 but rather you want to construct a complex128 value where you specify the real part.
For that can use the builtin complex() function:
func complex(r, i FloatType) ComplexType
Using it your sqrt() function:
func sqrt(x float64) string {
if x < 0 {
return fmt.Sprint(cmplx.Sqrt(complex(x, 0)))
}
return fmt.Sprint(math.Sqrt(x))
}
Try it on the Go Playground.
Note:
You can calculate the square root of a negative float number without using complex numbers: it will be a complex value whose real part is 0 and imaginary part is math.Sqrt(-x)i (so the result: (0+math.Sqrt(-x)i)):
func sqrt2(x float64) string {
if x < 0 {
return fmt.Sprintf("(0+%.15fi)", math.Sqrt(-x))
}
return fmt.Sprint(math.Sqrt(x))
}

Calculating large exponentiation in Golang

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
}

Resources