Precision loss when printing floats as strings [closed] - go

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
It just happened to me that if I store int number into a struct and later apply division with them. The precision would be lost.
func main() {
var x = 94911151
var y = 94911150
// If we use the value to calculate division directly, it would be fine
var result1 = float64(94911151)/94911150
var result2 = float64(x)/float64(y)
fmt.Println(result1, result2)
// If we pass the values directly as parameter into a function and then apply division, it would be fine
getParas(x,y)
// If we pass the values into a stuct, and then retrieve the value from struct, then apply division, the precision would be lost.
getLinearParas(Point{x,y},Point{0,0})
}
func getParas(a int, b int){
diffX := a -0
diffY := b-0
c:= float64(diffX) / float64(diffY)
fmt.Println(c)
}
type Point struct{
X int
Y int
}
func getLinearParas(point1 Point, point2 Point) {
diffX := point1.X - point2.X
diffY := point1.Y - point2.Y
a := float64(diffX) / float64(diffY)
fmt.Printf("diffY: %d; diffX:%d ; a:%f \n", diffY, diffX, a)
}
Like the code, If I put int values into a struct, and later apply division on them. the precision would be lost somehow.
The result of running above code is
1.00000001053617 1.00000001053617
1.00000001053617
diffY: 94911150; diffX:94911151 ; a:1.000000
Or you can try it yourself in playground
https://play.golang.org/p/IDS18rfv9e6
Could anyone explain why this happens? and how to avoid such loss?
Thank you very much.

Change %f in the format string to %v or %g or %.14f. fmt.Println prints things with the equivalent of %v, %v for float64 is treated as %g. %f prints values with 6 significant digits by default, %g uses "the smallest number of digits necessary to identify the value uniquely".

Related

why the length of this go slice is 4 and why the output has the space in slice? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I am new to golang and while running this code snippet I am getting the len as 4, trying to understand why so ?
package main
import "fmt"
type phone struct {
model string
camera Camera
ram int
}
type Camera struct {
lens string
aparature int
}
func main() {
var m = make(map[string]phone)
myphn1 := phone{model: "iphone", camera: Camera{"20", 4}, ram: 6}
myphn2 := phone{model: "pixel", camera: Camera{"50", 2}, ram: 6}
m["myphn1"] = myphn1
m["myphn2"] = myphn2
var k = make([]string, len(m))
for key, _ := range m {
k = append(k, key)
}
fmt.Println(k)
fmt.Println(len(k))
}
I understand this adds size of 2 while creating, but while printing it gives somelike this , is the space in answer for 2 unallocated entries ?
[ myphn2 myphn1]
4
This creates a slice of length 2 (len(m) is 2 here):
var k = make([]string, len(m))
This adds two elements to it, for a total of 4:
for key, _ := range m {
k = append(k, key)
}
If you want to preallocate a slice, you need to provide a length of zero along with the desired capacity:
var k = make([]string, 0, len(m))
This is covered with examples in the Tour of Go.
You create a slice with length 2, and appended two more elements to it, so the length is 4.
what you probably want to do is to create a slice with capacity 2:
var k = make([]string,0,len(m))

Understanding the switch statement and pointers in Go [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I can't figure out why this Go code with pointers and using the switch statement prints out "a":
import "fmt"
func main() {
var a, b int
var c = &b
switch *c {
case a:
fmt.Println("a")
case b:
fmt.Println("b")
default:
fmt.Println("c")
}
}
Any hints to this?
a and b are both zero (the zero value for integers).
Initializing c = &b means that c is a *int pointing to b.
Moving on to the switch statement, we are checking the value of *c which dereferences c and is the value of b, which is 0.
Since a is also zero, the first case matches.
You can swap the case a and case b statements and put b first. In that case, it will print b since it is now the first matching case:
package main
import "fmt"
func main() {
var a, b int
var c = &b
switch *c {
case b:
fmt.Println("b")
case a:
fmt.Println("a")
default:
fmt.Println("c")
}
}

How to get nearest int in operation on integers in golang? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I'd like to get nearest value of an operation envolving division of two integers. My initial function is like this, which always rounds to the lower integer.
func Percent(x int, y int) int {
p := x * 100 / y
return p
}
So for example when the result is 5.75, I'd like to be rounded to 6, but the above function returns 5.
I tried to use math.Round but it needs receive a float type and returns a float type. So that needs lots of conversion which gets dirty whn there are many parameters in the operation.
So I'm wondering what is the clean idomatic way to round to nearest integer?
Your operations are using all integer so the output will be an integer, so definitely you need to cast them to float first, then you can convert float to nearest int (5.75 to 5)
For that below code will work for you. You even don't need to use math.Round
func Percent(x int, y int) int {
p := float64(x * 100) / float64(y)
return int(p+0.5)
}
Just create float values from your ints, then an int value from a rounded float result:
func RoundPercent(x int, y int) int {
p := float64(x * 100) / float64(y)
return int(math.Round(p))
}

Why do we add & in the following script, if it does not make any change on the result? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
package main
import (
"fmt"
"math"
"reflect"
)
type Vertex struct {
X, Y float64
}
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
v := &Vertex{3, 4} // Whether or not with "&", the values don't change below.
fmt.Printf("Before scaling: %+v, Abs: %v\n", v, v.Abs())
v.Scale(5)
fmt.Printf("After scaling: %+v, Abs: %v\n", v, v.Abs())
fmt.Println(reflect.TypeOf(Vertex{3,4}))
}
Hello, I am learning golang now. I do not understand what is the use of adding "&", if it does not make any change on the result value?
I thought we add "&" to variables to get the memory address. If we can add "&" to Vertex{3,4}, does this mean it is variable? Confused.
I assume you're talking about Vertex vs &Vertex? Yes, adding & means that v now contains an address to a struct of type Vertex, whereas without the &, v would hold the struct directly.
In your example, using the address, or the struct directly, makes no difference. In many other cases, the distinction is very important.

How to get a sample of random numbers in golang? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
Or I have to use straightforward way like:
var arr []int
for i := 0; i < 5; i++ {
arr = append(arr, rand.Intn(100))
}
What you did is clean and fast enough. What you could improve on it is to pre-allocate the slice and fill it using a for.. range loop like this:
s := make([]int, 5)
for i := range s {
s[i] = rand.Intn(100)
}
The math/rand package also has a rand.Read() function which fills a slice with random bytes. So if you want to fill a []byte slice with random data, this is all it takes:
s := make([]byte, 100)
rand.Read(s) // This never returns an error
Another interesting way would be to take advantage of rand.Rand being an io.Reader. Which means it has a Read() method which fills a []byte with random data.
This combined with the encoding/binary package, you can "fill" variables with random data. Create and pass a rand.Rand to the binary.Read() function as the source, and that's it.
This is how it would look like:
r := rand.New(rand.NewSource(time.Now().UnixNano()))
s := make([]int32, 5)
err := binary.Read(r, binary.BigEndian, &s)
if err != nil {
panic(err)
}
fmt.Println(s)
Output:
[203443513 1611652563 -235795288 8294855 -802604260]
This is "cool" enough to even fill structs for example:
var point struct{ X, Y int16 }
err = binary.Read(r, binary.BigEndian, &point)
if err != nil {
panic(err)
}
fmt.Printf("%+v", point)
Output:
{X:-15471 Y:2619}
Try these examples on the Go Playground.
One handicap of using binary.Read() is that–understandably–it can only fill values of fixed-size types, and the most famous exception is the common int type, whose size is not fixed (architecture dependent). So you can't fill an []int slice or a struct with a field of int type. That's why I used int32 and int16 types in the above examples.
Of course in these solutions you could not limit the range of random numbers that are used to fill your variables. For that, the initial loop is still easier.

Resources