How to take a cube root in Go? - go

I'm writing a cube root function in Google Go using Newton's method. I want to check the results using math/cmplx.Pow(), but for the life of me, I can't figure out how. How do I do this?

Have you tried myCubicRootOfx = Pow(x, 1.0/3) ?
edited: thanks to Jason McCreary comment:
We cannot use 1/3 as the 2nd parameter to Pow as this is a integer division and hence doesn't produce the expected 1/3 value. By using 1.0/3 or 1/3.0 etc. we effectively produce a float with the 0.333333... value.

I wrote the cube root function using Newton's method as part of the Go Tour Exercise 47. Perhaps the two functions below (Cbrt1 and Cbrt) are helpful.
package main
import (
"fmt"
"math/cmplx"
)
// Newton's method cube root function that hopes for
// convergence within 20 iterations
func Cbrt1(x complex128) complex128 {
var z complex128 = x
for i:= 0; i < 20; i++ {
z = z - ((z*z*z - x) / (3.0*z*z))
}
return z
}
// Newton's method cube root function that runs until stable
func Cbrt(x complex128) complex128 {
var z, z0 complex128 = x, x
for {
z = z - ((z*z*z - x) / (3.0*z*z))
if cmplx.Abs(z - z0) < 1e-10 {
break
}
z0 = z
}
return z
}
func main() {
fmt.Println(Cbrt(2.0) , "should match" , cmplx.Pow(2, 1.0/3.0))
}

As you're using Newton's method, I suppose you're starting with a positive real number.
So you don't need complex numbers.
You may simply do
package main
import (
"fmt"
"math"
)
func main() {
x := 100.0
root := math.Pow(x, 1.0/3.0)
fmt.Println(root)
}

For example,
package main
import (
"fmt"
"math/cmplx"
)
func main() {
var x complex128
x = -8
y := cmplx.Pow(x, 1.0/3.0)
fmt.Println(y)
x = -27i
y = cmplx.Pow(x, 1.0/3.0)
fmt.Println(y)
x = -8 - 27i
y = cmplx.Pow(x, 1.0/3.0)
fmt.Println(y)
x = complex(-8, -27)
y = cmplx.Pow(x, 1.0/3.0)
fmt.Println(y)
}
Output:
(1+1.732050807568877i)
(2.5980762113533156-1.4999999999999996i)
(2.4767967587776756-1.7667767800295509i)
(2.4767967587776756-1.7667767800295509i)
The Go Programming Language Specification
Package cmplx

Looks like go has changed more recently than some of the other answers, so I figured I would update - they built cuberoot right into math as Cbrt. It takes, and returns, a float64. A quick reference is at godoc math | grep Cbrt (if you've got godoc installed, which I highly recommend)
import "math"
func main() {
var x float64 = math.Cbrt(8)
fmt.Println(x) // prints 2
}

try something like this
package main
import(
"fmt"
"math/cmplx"
)
func Cbrt(x complex128) complex128 {
z := complex128(1)
for i:=0;i<100;i++ { // OR JUST for{ since you will outrun complex128 in worth case
last_z := z
z = z - ((z*z*z - x)/(3 *z*z))
if last_z == z{
return z
}
}
return z
}
func main() {
fmt.Println("good enough", Cbrt(9))
fmt.Println("builtin", cmplx.Pow(9, 1.0/3.0))
}

Related

How should we calc money (decimal, big.Float)

Can someone tell the right way to calculate finance data in Go. I tryed to use big.Float but prob I miss something. The core goal is to calculate numbers with flaoting point and precision from 2 to 4 without any losses.
0.15 + 0.15 always should be 0.30.
float try:
https://play.golang.org/p/_3CXtRRNcA0
big.Float try:
https://play.golang.org/p/zegE__Dit1O
Floating-point is imprecise. Use integers (int64) scaled to cents or fractional cents.
For example, cents,
package main
import (
"fmt"
)
func main() {
cents := int64(0)
for i := 0; i <= 2; i++ {
cents += 15
fmt.Println(cents)
}
fmt.Printf("$%d.%02d\n", cents/100, cents%100)
}
Playground: https://play.golang.org/p/k4mJZFRUGVH
Output:
15
30
45
$0.45
For example, hundredths of a cent rounded,
package main
import "fmt"
func main() {
c := int64(0) // hundredths of a cent
for i := 0; i <= 2; i++ {
c += 1550
fmt.Println(c)
}
c += 50 // rounded
fmt.Printf("$%d.%02d\n", c/10000, c%10000/100)
}
Playground: https://play.golang.org/p/YGW9SC7OcU3
Output:
1550
3100
4650
$0.47
you can try https://github.com/shopspring/decimal if you really concern about precision,
try this code:
package main
import (
"fmt"
"github.com/shopspring/decimal"
)
func main() {
z := decimal.NewFromFloat(0)
b := decimal.NewFromFloat(0.15)
z = z.Add(b)
z = z.Add(b)
z = z.Add(b)
fmt.Println("z value:", z)
testz := z.Cmp(decimal.NewFromFloat(0.45)) == 0
fmt.Println("is z pass the test? ", testz)
}
Playground: https://play.golang.org/p/g_fSGlXPKDH
Output:
z value: 0.45
is z pass the test? true

Is it ok to call a function as part of a for loop condition?

Below are two attempts to solve the exercise at https://tour.golang.org/flowcontrol/8. One version makes a function call as part of the for condition, but this doesn't work - it doesn't even execute the loop body. If I move the condition inside the loop itself, it works as I expected. Why?
package main
import (
"fmt"
"math"
)
func Sqrt_working(x float64) float64 {
var z float64 = 1.0
for {
if math.Abs((z*z) - x) < 0.0001 {
break
}
z -= ((z*z - x) / (2*z))
}
return z
}
func Sqrt_not_working(x float64) float64 {
var z float64 = 1.0
for math.Abs((z*z) - x) < 0.0001 {
z -= ((z*z - x) / (2*z))
}
return z
}
func main() {
fmt.Println(Sqrt_working(2))
fmt.Println(Sqrt_not_working(2))
}
Output
1.4142156862745099
1
Your if condition is signalling when the loop should stop, but the for condition signals when the loop should continue.
To see the desired result, invert your for condition:
for math.Abs((z*z) - x) >= 0.0001 {
z -= ((z*z - x) / (2*z))
}

What's wrong with this simple script?

I study functions, wrote a simple script for the textbook, and there were 2 errors.
package main
import "fmt"
func zero(x int) {
x = 0
return x
}
func main() {
x := 5
x = zero(x)
fmt.Println(x)
}
too many arguments to return (string return x)
How is "too many"? It's only one!
zero(x) used as value (string x = zero(x))
I don't understand what he says to me.
int in func
package main
import "fmt"
func zero(x int) int {
x = 0
return x
}
func main() {
x := 5
x = zero(x)
fmt.Println(x)
}
package main
import "fmt"
func zero(x int) int {
x = 0
return x
}
func main() {
x := 5
x = zero(x)
fmt.Println(x)
}
I believe this is closer to the original idea...
package main
import "fmt"
func zero(x *int) {
*x = 0
return
}
func main() {
x := 5
zero(&x)
fmt.Println(x)
}
too many means that your function is returning more values that the function signature specifies.
In your case, your function signature func zero(x *int), says that this function doesn't returns ANY params, and inside the function body, you're returning ONE value: return x. So 1 is too many for 0 expected. Exactly 1 more.
Then zero(x) used as value is telling you that you're calling a function that doesn't return ANY value, and you're trying to assign the non-existent return value to a variable: x = zero(x).
That's why the compiler tells you about using zero(x) as a value

Go Random number always return 168

I am a complete noob in regards to Go.
I am trying to make a an arbitrary function that returns two random numbers added together.
I have pasted my code below, and cannot figure out why it always returns 168!
package main
import(
"fmt"
"math/rand"
)
func add(x int, y int) int{
return x + y
}
var a int = rand.Intn(100)
var b int = rand.Intn(100)
func main() {
fmt.Println(add(a, b))
}
You have to specify seed to get different numbers. It is outlined in documentation:
Top-level functions, such as Float64 and Int, use a default shared
Source that produces a deterministic sequence of values each time a
program is run. Use the Seed function to initialize the default Source
if different behavior is required for each run.
And some reference about Seed
Seed uses the provided seed value to initialize the default Source to
a deterministic state. If Seed is not called, the generator behaves as
if seeded by Seed(1).
And you can see an example in the go cookbook:
rand.Seed(time.Now().Unix())
So wrapping up, you will have something like this:
package main
import(
"fmt"
"math/rand"
"time"
)
func add(x int, y int) int{
return x + y
}
func main() {
rand.Seed(time.Now().Unix())
var a int = rand.Intn(100)
var b int = rand.Intn(100)
fmt.Println(add(a, b))
}

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