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
Related
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
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))
}
Learning Go and try to write an App which take bit depth as input, when bitDepth == 8, define a varable as var y []byte, When bitDepth == 10, define a variable var y []uint16
What's the right way to do it in Go?
Because there are no generics in go, you will still have to do type assertions if you use an empty interface i.e. interface{}.
The best option is to define an interface that provides all of the functionality you need, and implement it for all the datatypes you need to wrap.
package main
type SliceWrapper interface {
Slice(start, end int) SliceWrapper
Index(index int) int
}
func NewSlice(bitDepth int) SliceWrapper {
switch bitDepth {
case 8:
return make(Uint8Wrapper)
case 16:
return make(Uint16Wrapper)
}
}
type Uint8Wrapper []uint8
func (u Uint8Wrapper) Slice(s, e int) SliceWrapper {
return u[s:e]
}
func (u Uint8Wrapper) Index(i int) int {
return u[i]
}
type Uint16Wrapper []uint16
func (u Uint16Wrapper) Slice(s, e int) SliceWrapper {
return u[s:e]
}
func (u Uint16Wrapper) Index(i int) int {
return u[i]
}
You will need more functionality than that I am sure, but it is way cleaner than throwing interface{} around everywhere.
one way is:
package main
import (
"fmt"
)
func virtualVar(bitDepth int) interface{} {
var v interface{}
switch bitDepth {
case 8:
y := []byte{1, 2}
v = y
case 16:
y := []uint16{12345, 11000}
v = y
}
return v
}
func main() {
a := virtualVar(8)
b := virtualVar(16)
fmt.Println(a) //[1 2]
fmt.Println(b) //[12345 11000]
}
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
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))
}