keep negative number in string negative when converted golang - go

I'm trying to extract LAT / LONG from a string, but my negative float for the longitude keeps changing to zero, so far I have:
loc1 := "33.333333"
loc2 := "-44.44444"
However when using the strvconv package my results:
nloc1, _ := strconv.ParseFloat(loc1, 64)
RESULT: 33.333333 (successful float64)
nloc2, _ := strconv.ParseFloat(loc2, 64)
RESULT: 0 (successful float64)
any ideas on how to stop that from going to zero? I need to keep it the same number just a negative float. Thanks in advance!
EDIT:: The issue was a leading space, once reformatted, it works as it should. Thanks all.

This usually happens when you have leading or trailing whitespaces.
Try this:
nloc2, _ := strconv.ParseFloat(strings.TrimSpace(loc2), 64)

Related

Is there a simple method for square root of big.Rat?

I need to find the square root of a big.Rat. Is there a way to do it without losing (already existing) accuracy?
For example, I could convert the numerator and denominator into floats, get the square root, and then convert it back...
func ratSquareRoot(num *big.Rat) *big.Rat {
f, exact := num.Float64() //Yuck! Floats!
squareRoot := math.Sqrt(f)
var accuracy int64 = 10 ^ 15 //Significant digits of precision for float64
return big.NewRat(int64(squareRoot*float64(accuracy)), accuracy)
// ^ This is now totally worthless. And also probably not simplified very well.
}
...but that would eliminate all of the accuracy of using a rational. Is there a better way of doing this?
The big.Float type has a .Sqrt(x) operation, and handles defining explicitly the precision you aim for. I'd try to use that and convert the result back to a Rat with the same operations in your question, only manipulating big.Int values.
r := big.NewRat(1, 3)
var x big.Float
x.SetPrec(30) // I didn't figure out the 'Prec' part correctly, read the docs more carefully than I did and experiement
x.SetRat(r)
var s big.Float
s.SetPrec(15)
s.Sqrt(&x)
r, _ = s.Rat(nil)
fmt.Println(x.String(), s.String())
fmt.Println(r.String(), float64(18919)/float64(32768))
playground

Golang cannot convert []byte("1575455669.4") to float64 using math.Float64frombits

I have the following code:
x := []byte("1575455669.4")
bits := binary.LittleEndian.Uint64(x)
f := math.Float64frombits(bits)
On calling fmt.Println(f) I expect 1.5754556694e+09. But instead I end up with 1.451098468672448e-47
When I try the same conversion through strconv.ParseFloat(string(x), 64) I get the correct result. What am I doing wrong here?
This:
x := []byte("1575455669.4")
will give you the (UTF-8 encoded) bytes of the "1575455669.4" string. This has nothing to do with the memory representation of the floating point number 1575455669.4 which uses the IEEE 754 standard. But what you do next would assume just that:
bits := binary.LittleEndian.Uint64(x)
f := math.Float64frombits(bits)
You have a number given as its base-10 string representation, you have to use strconv.ParseFloat(string(x), 64) to parse it and have it as a float64.

How can I truncate float64 number to a particular precision?

I want to truncate 1.234567 into a 3-fraction digit floating point number, but the result is not what I want.
E.g: 1.234567 => 1.234
package main
import (
"strconv"
"fmt"
)
func main() {
f := 1.234567
fmt.Println(strconv.FormatFloat(f, 'f', 3, 64)) //1.235
fmt.Printf("%.3f", f) //1.235
}
Can anyone tell me how to do this in Go?
The naive way (not always correct)
For truncation, we could take advantage of math.Trunc() which throws away the fraction digits. This is not exactly what we want, we want to keep some fraction digits. So in order to achieve what we want, we may first multiply the input by a power of 10 to shift the wanted fraction digits to the "integer" part, and after truncation (calling math.Trunc() which will throw away the remaining fraction digits), we can divide by the same power of 10 we multiplied in the beginning:
f2 := math.Trunc(f*1000) / 1000
Wrapping this into a function:
func truncateNaive(f float64, unit float64) float64 {
return math.Trunc(f/unit) * unit
}
Testing it:
f := 1.234567
f2 := truncateNaive(f, 0.001)
fmt.Printf("%.10f\n", f2)
Output:
1.2340000000
So far so good, but note that we perform arithmetic operations inside truncateNaive() which may result in unwanted roundings, which could alter the output of the function.
For example, if the input is 0.299999999999999988897769753748434595763683319091796875 (it's representable by a float64 value exactly, see proof), the output should be 0.2999000000, but it will be something else:
f = 0.299999999999999988897769753748434595763683319091796875
f2 = truncateNaive(f, 0.001)
fmt.Printf("%.10f\n", f2)
Output:
0.3000000000
Try these on the Go Playground.
This wrong output is probably not acceptable in most cases (except if you look at it from a way that the input is very close to 0.3–difference is less than 10-16–to which the output is 0.3...).
Using big.Float
To properly truncate all valid float64 values, the intermediate operations must be precise. To achieve that, using a single float64 is insufficient. There are ways to split the input into 2 float64 values and perform operations on them (so precision is not lost) which would be more efficient, or we could use a more convenient way, big.Float which can be of arbitrary precision.
Here's the "transcript" of the above truncateNaive() function using big.Float:
func truncate(f float64, unit float64) float64 {
bf := big.NewFloat(0).SetPrec(1000).SetFloat64(f)
bu := big.NewFloat(0).SetPrec(1000).SetFloat64(unit)
bf.Quo(bf, bu)
// Truncate:
i := big.NewInt(0)
bf.Int(i)
bf.SetInt(i)
f, _ = bf.Mul(bf, bu).Float64()
return f
}
Testing it:
f := 1.234567
f2 := truncate(f, 0.001)
fmt.Printf("%.10f\n", f2)
f = 0.299999999999999988897769753748434595763683319091796875
f2 = truncate(f, 0.001)
fmt.Printf("%.10f\n", f2)
Output is now valid (try it on the Go Playground):
1.2340000000
0.2990000000
You need to truncate decimals manually, either on string level or with math.Floor like https://play.golang.org/p/UP2gFx2iFru.

GoLang for loop with floats creates error

Can someone explain the following. I have a function in go that accepts a couple of float64 and then uses this value to calculate a lot of other values. The function looks like
func (g *Geometry) CalcStresses(x, zmax, zmin float64)(Vertical)
the result is put into a struct like
type Vertical struct {
X float64
Stresses []Stress
}
Now the funny thing is this. If I call the function like this;
for i:=14.0; i<15.0; i+=0.1{
result := geo.CalcStresses(i, 10, -10)
}
then I get a lot of results where the Stress array is empty, antoher interesting detail is that x sometimes shows like a number with a LOT of decimals (like 14.3999999999999999998)
However, if I call the function like this;
for i:=0; i<10; i++{
x := 14.0 + float64(i) * 0.1
result := geo.CalcStresses(x,10,-10)
}
then everything is fine.
Does anyone know why this happens?
Thanks in advance,
Rob
Not all real numbers can be represented precisely in binary floating point format, therefore looping over floating point number is asking for trouble.
From Wikipedia on Floating point
The fact that floating-point numbers cannot precisely represent all real numbers, and that floating-point operations cannot precisely represent true arithmetic operations, leads to many surprising situations. This is related to the finite precision with which computers generally represent numbers.
For example, the non-representability of 0.1 and 0.01 (in binary) means that the result of attempting to square 0.1 is neither 0.01 nor the representable number closest to it.
This code
for i := 14.0; i < 15.0; i += 0.1 {
fmt.Println(i)
}
produces this
14
14.1
14.2
14.299999999999999
14.399999999999999
14.499999999999998
14.599999999999998
14.699999999999998
14.799999999999997
14.899999999999997
14.999999999999996
You may use math.big.Rat type to represent rational numbers accurately.
Example
x := big.NewRat(14, 1)
y := big.NewRat(15, 1)
z := big.NewRat(1, 10)
for i := x; i.Cmp(y) < 0; i = i.Add(i, z) {
v, _ := i.Float64()
fmt.Println(v)
}

Convert returned values to a specific type

I'm just getting started with go and I've come across the following "problem".
I'm using a function which returns 4 unsigned 32 bit integers, and I was wondering what the best method to convert these values to 8 bit integers when I'm assigning them. (Or if it is possible). I have got it to work by assigning them to uint32, then converting them after that but I was wondering if there is a more concise way of doing it.
Example:
r, g, b, _ := image.At(x, y).RGBA() // ideally convert them at this stage
So Image.At returns uint32, but I would like r,g,b to be uint8
Thanks
Go has no syntax for what you want there. You're best bet is to just do it in the next line down.
rbig, gbig, bbig := image.At(x, y).RGBA()
r, g, b := uint8(rbig), uint8(gbig), uint8(bbig)
If that really annoys you though then just make a helper function
func convert(i, j, k, _ uint32) (uint8, uint8, uint8) { return uint8(i), uint8(j), uint8(k) }
r, g, b := convert(image.At(x, y).RGBA())
Still a minimum of two lines but you can reuse the function anywhere you need it and the call site might look a little cleaner to you.

Resources