Parsefloat give output in scientific format in golang - go

i am trying to parse this string "7046260" using Parsefloat function in golang , but i am getting output in scientific format 7.04626e+06. i want the output in the format 7046260. how to get this?
package main
import (
"fmt"
"strconv"
)
func main() {
Value := "7046260"
Fval, err := strconv.ParseFloat(Value, 64)
if err == nil {
fmt.Println(Fval)
}
}
ouput :- 7.04626e+06

Parsefloat give output in scientific format in golang
i am trying to parse this string "7046260" using Parsefloat function in golang , but i am getting output in scientific format 7.04626e+06. i want the output in the format 7046260
You're confusing the floating-point value's (default) formatted output with its internal representation.
ParseFloat is working fine.
You just need to specify an output format:
See the fmt package documentation.
Use Printf to specify a format-string.
Use the format %.0f to instruct Go to print the value as-follows:
% marks the start of a placeholder.
. denotes default width (i.e. don't add leading or trailing zeroes).
0 denotes zero radix precision (i.e. don't print any decimal places, even if the value has them)
f denotes the end of the placeholder, and that the placeholder is for a floating-point value.
I have a few other recommendations:
Local variables in Go should use camelCase, not PascalCase. Go does not encourage the use of snake_case.
You should check err != nil after each nil-returning function returns and either fail-fast (if appropriate), pass the error up (and optionally log it), or handle it gracefully.
When working with floating-point numbers, you should be aware of NaN's special status. The IsNaN function is the only way to correctly check for NaN values (because ( aNaNValue1 == math.NaN ) == false).
The same applies in all languages that implement IEEE-754, including Java, JavaScript, C, C#.NET and Go.
Like so:
package main
import (
"fmt"
"strconv"
"math"
"log"
)
func main() {
numberText := "7046260"
numberFloat, err := strconv.ParseFloat(numberText, 64)
if err != nil {
log.Fatal(err)
}
if math.IsNaN(numberFloat) {
log.Fatal("NaN value encountered")
}
fmt.Printf("%.0f",numberFloat)
fmt.Println()
}

Related

html/template is not showing a float value with e+07 notation in exact decimal places

I'm trying an example where I'm passing a value 1.8e+07 to the TestVal field of struct Student. Now I want this 1.8e+07 value to be in exact decimal places but it is not doing so. It is able to show the value in exact decimal places(180000) if the value is 1.8e+05. But if it is greater than e+05 then it is unable to show it.
Example
package main
import (
"fmt"
"os"
"text/template"
)
// declaring a struct
type Student struct {
Name string
TestVal float32
}
// main function
func main() {
std1 := Student{"AJ", 1.8e+07}
// "Parse" parses a string into a template
tmp1 := template.Must(template.New("Template_1").Parse("Hello {{.Name}}, value is {{.TestVal}}"))
// standard output to print merged data
err := tmp1.Execute(os.Stdout, std1)
// if there is no error,
// prints the output
if err != nil {
fmt.Println(err)
}
}
Please help.
That's just the default formatting for floating point numbers. The package doc of fmt explains it: The %v verb is the default format, which for floating numbers means / reverts to %g which is
%e for large exponents, %f otherwise. Precision is discussed below.
If you don't want the default formatting, use the printf template function and specify the format you want, for example:
{{printf "%f" .TestVal}}
This will output (try it on the Go Playground):
Hello AJ, value is 18000000.000000
Or use:
{{printf "%.0f" .TestVal}}
Which will output (try it on the Go Playground):
Hello AJ, value is 18000000
See related:
Format float in golang html/template

How to convert the string representation of a Terraform set of strings to a slice of strings

I've a terratest where I get an output from terraform like so s := "[a b]". The terraform output's value = toset([resource.name]), it's a set of strings.
Apparently fmt.Printf("%T", s) returns string. I need to iterate to perform further validation.
I tried the below approach but errors!
var v interface{}
if err := json.Unmarshal([]byte(s), &v); err != nil {
fmt.Println(err)
}
My current implementation to convert to a slice is:
s := "[a b]"
s1 := strings.Fields(strings.Trim(s, "[]"))
for _, v:= range s1 {
fmt.Println("v -> " + v)
}
Looking for suggestions to current approach or alternative ways to convert to arr/slice that I should be considering. Appreciate any inputs. Thanks.
Actually your current implementation seems just fine.
You can't use JSON unmarshaling because JSON strings must be enclosed in double quotes ".
Instead strings.Fields does just that, it splits a string on one or more characters that match unicode.IsSpace, which is \t, \n, \v. \f, \r and .
Moeover this works also if terraform sends an empty set as [], as stated in the documentation:
returning [...] an empty slice if s contains only white space.
...which includes the case of s being empty "" altogether.
In case you need additional control over this, you can use strings.FieldsFunc, which accepts a function of type func(rune) bool so you can determine yourself what constitutes a "space". But since your input string comes from terraform, I guess it's going to be well-behaved enough.
There may be third-party packages that already implement this functionality, but unless your program already imports them, I think the native solution based on the standard lib is always preferrable.
unicode.IsSpace actually includes also the higher runes 0x85 and 0xA0, in which case strings.Fields calls FieldsFunc(s, unicode.IsSpace)
package main
import (
"fmt"
"strings"
)
func main() {
src := "[a b]"
dst := strings.Split(src[1:len(src)-1], " ")
fmt.Println(dst)
}
https://play.golang.org/p/KVY4r_8RWv6

How to get the natural log of a big integer

I am trying to convert a string to integer and then to calculate its log.
My first approach was to convert the string using strconv library, but I got an error about the length of the string to be converted.
After that, I used math/big library which worked fine. Now I am not able to apply math.Log()on the resulted big integer.
Code:
package main
import (
"fmt"
"math"
"math/big"
)
func main() {
bb := "11948904162160164791281681976941230184120142151411311314211115130161285142991119211447"
bi := big.NewInt(0)
if _, ok := bi.SetString(bb, 10); ok {
fmt.Println(math.Log(bi))
} else {
fmt.Printf("error parsing line %#v\n", bb)
}
}
Error:
cannot use bi (type *big.Int) as type float64 in argument to math.Log
There are very few situations in which you'd need a precision greater than the one provided by the standard float64 type.
But just to satisfy any "midnight crazy ideas" (or even some very in-depth scientific research!) anyone might run into, Rob Pike's implementations of some operations with big floats are probably the best you can get right now with Go. The log function can be found here.

Golang get decimal separator for current culture

Is there a way in Golang to get the current OS decimal separator in windows?
I know that in the Geographic area settings in control panel you can assign your custom decimal separator, so there must be a way to get this value... or no?
I want to use fmt.Printf() and format any float with the OS current decimal symbol.
I want to use fmt.Printf() and format any float with the OS current decimal symbol.
To get the current language OS, you might use a cross platform package such as https://github.com/cloudfoundry-attic/jibber_jabber
To print localized texts you might use the text package available here https://godoc.org/golang.org/x/text
Example
package main
import (
"fmt"
"github.com/cloudfoundry/jibber_jabber"
"golang.org/x/text/language"
"golang.org/x/text/message"
)
func main() {
userLanguage, err := jibber_jabber.DetectLanguage()
if err != nil {
panic(err)
}
fmt.Println("Language:", userLanguage)
tagLanguage := language.Make(userLanguage)
fmt.Println("Language:", tagLanguage)
{
p := message.NewPrinter(language.BritishEnglish)
p.Printf("There are %v flowers in our garden.\n", 1500)
}
{
p := message.NewPrinter(tagLanguage)
p.Printf("There are %v flowers in our garden.\n", 1500)
}
}
As you can see you don t directly use the fmt package anymore, instead you have to create a Printer and use this one to display the texts appropriately.
to get more details about this package usage you can read https://phraseapp.com/blog/posts/internationalization-i18n-go/
Is there a way in Golang to get the current OS decimal separator in windows?
I have not been able to determine how to extract this information from the text package.

prevent json.Marshal time.Time removing trailing zeros

I have code similar to the following
package main
import (
"fmt"
"time"
"encoding/json"
)
type Message struct {
Time time.Time `json:"timestamp,omitempty"`
}
func main() {
t, _ := time.Parse("2006-01-02T15:04:05.999Z07:00", "2017-05-01T15:04:05.630Z")
msg := Message{
Time: t,
}
bs, _ := json.Marshal(msg)
fmt.Println(string(bs[:]))
}
This prints
{"timestamp":"2017-05-01T15:04:05.63Z"}
How can I make json marshalling keep the trailing 0? I.e., to print this?
{"timestamp":"2017-05-01T15:04:05.630Z"}
Edit:
Here's the playground https://play.golang.org/p/9p3kWeiwu2
time.Time always marshals to RFC 3339, only including sub-second precision if present: https://golang.org/pkg/time/#Time.MarshalJSON
You can write your own custom version using a named time.Time type, or you can define a custom marshal function for your structure, or you can make your structure hold a string in that place instead. In any case, if you want to use the same format, but including trailing zeros, you need to use a modified version of the RFC3339Nano constant.
Its value is: "2006-01-02T15:04:05.999999999Z07:00".
The 9's at the end mean "include until the rightmost non-zero value, omit after that". If you change those 9's to 0's, it will always include them. For example, if you always want millisecond precision (and nothing after that, regardless of whether it's non-zero or not), you would use:
"2006-01-02T15:04:05.000Z07:00"
If you feed that to Format() on your time.Time value, you'll get out the string you want, and can thus include it in the JSON.
Functioning example: https://play.golang.org/p/oqwnma6odw

Resources