Floating point string representation

709 views
Skip to first unread message

Johann Höchtl

unread,
Feb 14, 2011, 4:29:09 PM2/14/11
to golang-nuts
Supose I have a float 12.00000012
When I do a Printf("%.4f", ...) it would return "12.0000"
In such a case I would like to have a clear "12" printed out. Is there
a format specifier which will omit the suffix in case it would be all
zero or do I have to write my own formating routine?

Johann

Andrew Gerrand

unread,
Feb 14, 2011, 4:36:02 PM2/14/11
to Johann Höchtl, golang-nuts

If you just use %f (or Print()) to format a float, the default is to
provide as many decimal places as are required to describe the value
precisely.

Eg: http://goo.gl/goT4M

Andrew

Andrew Gerrand

unread,
Feb 14, 2011, 4:40:42 PM2/14/11
to Johann Höchtl, golang-nuts

Actually I'm mistaken: what I said is true of %v and %g but not %f.

Andrew

Johann Höchtl

unread,
Feb 14, 2011, 4:57:45 PM2/14/11
to golang-nuts


On Feb 14, 10:36 pm, Andrew Gerrand <a...@golang.org> wrote:
The problem get's clear by executing this snippet:

http://goo.gl/pU4Ad

> Andrew

Johann Höchtl

unread,
Feb 14, 2011, 5:05:08 PM2/14/11
to golang-nuts
Shortening s'not working so I post it here:
package main

import "fmt"

type BMNCoord struct {
Right, Height, RelHeight float64
}

func NewBMNCoord(r, h, rh float64) *BMNCoord {
return &BMNCoord{Right:r, Height:h}
}

func (co *BMNCoord) String() string {
return fmt.Sprintf("%f %f", co.Right, co.Height)
}

func main() {
f := 2000
fmt.Println(f)
coord := NewBMNCoord(2000.0, 4000.0, 0)
fmt.Println(coord)
}


/* Output is:
2000
2000.000000 4000.000000
*/

Why doesn't the second printf hidden in a Sprintf not cut away the all
zero suffixes?


> > Andrew

Andrew Gerrand

unread,
Feb 14, 2011, 5:10:21 PM2/14/11
to Johann Höchtl, golang-nuts
On 14 February 2011 17:05, Johann Höchtl <johann....@gmail.com> wrote:
> Why doesn't the second printf hidden in a Sprintf not cut away the all
> zero suffixes?

Use %v instead of %f.

Andrew

Johann Höchtl

unread,
Feb 14, 2011, 5:27:44 PM2/14/11
to golang-nuts


On Feb 14, 11:10 pm, Andrew Gerrand <a...@golang.org> wrote:
> On 14 February 2011 17:05, Johann Höchtl <johann.hoec...@gmail.com> wrote:
>
> > Why doesn't the second printf hidden in a Sprintf not cut away the all
> > zero suffixes?
>
> Use %v instead of %f.
>
"%.3v" is doing what I want as it rounds at the third place after the
suffix and truncates to two places after the suffix. If the suffix
would be all zero, it is completely discarded.

0.5 is rounded towards zero.

This should be documented.

> Andrew

David Roundy

unread,
Feb 14, 2011, 5:31:44 PM2/14/11
to Johann Höchtl, golang-nuts
On Mon, Feb 14, 2011 at 2:27 PM, Johann Höchtl <johann....@gmail.com> wrote:
> On Feb 14, 11:10 pm, Andrew Gerrand <a...@golang.org> wrote:
>> On 14 February 2011 17:05, Johann Höchtl <johann.hoec...@gmail.com> wrote:
>>
>> > Why doesn't the second printf hidden in a Sprintf not cut away the all
>> > zero suffixes?
>>
>> Use %v instead of %f.
>>
> "%.3v" is doing what I want as it rounds at the third place after the
> suffix and truncates to two places after the suffix. If the suffix
> would be all zero, it is completely discarded.

In C or C++ (and most languages that support C-style printf), %.3g
will do what you want, and this also works in go. I just mention
this, since it's not unlikely that you'll end up wanting to do the
same thing in some other language some day, and %v is specific to go.
Also, I consider using %g to be more clear, since it documents within
the string that you expect a floating-point value.

> This should be documented.

I agree.
--
David Roundy

Russ Cox

unread,
Feb 14, 2011, 6:20:27 PM2/14/11
to Johann Höchtl, golang-nuts
> 0.5 is rounded towards zero.

Yes, and 1.5 is rounded towards two.
It's the standard rules.

Johann Höchtl

unread,
Feb 15, 2011, 5:09:02 PM2/15/11
to golang-nuts
I have to come back to this as it's not doing what I want. First: The
output should not be in scientific notation. As such, %g is not save,
as %g MAY print in scientific notation.

Take a look at this:
http://pastebin.com/2gh9was6

The output is
2000
2e+06 4e+07
70 30 <- <-- This line is good

but I would like it to be
2000000.1 40000000
70 30 <-- This line is good

(or 2000000.1=2= 40000000, depending on what the "2" in %.2g actually
means)

Changing the format specifier back to %f prints the all zero suffix.

Johann

Russ Cox

unread,
Feb 15, 2011, 5:14:50 PM2/15/11
to Johann Höchtl, golang-nuts
There is no way to do what you are asking with a format verb.
In fact package strconv does not even do what you are asking.

The closest you can get is to use

s := fmt.Sprintf("%.6f", f)
n := len(s)
for n > 0 && s[n-1] == '0' {
n--
}
if n > 0 && s[n-1] == '.' {
n--
}
s = s[:n]

If you put this in a String method on your own type then
you can use it to print your values by converting them to
that type in the call to fmt.Println or any of the other printers.

Russ

Johann Höchtl

unread,
Feb 15, 2011, 5:37:21 PM2/15/11
to golang-nuts


On Feb 15, 11:14 pm, Russ Cox <r...@golang.org> wrote:
> There is no way to do what you are asking with a format verb.
> In fact package strconv does not even do what you are asking.
>
> The closest you can get is to use
>
>     s := fmt.Sprintf("%.6f", f)
>     n := len(s)
>     for n > 0 && s[n-1] == '0' {
>         n--
>     }
>     if n > 0 && s[n-1] == '.' {
>         n--
>     }
>     s = s[:n]
>

Thank you! So hand-rolling. But it fit's my need. Actually I think
such a formatting flag would be useful.

Russ Cox

unread,
Feb 16, 2011, 11:04:43 AM2/16/11
to Johann Höchtl, golang-nuts
> Thank you! So hand-rolling. But it fit's my need. Actually I think
> such a formatting flag would be useful.

You can extend the formatting behavior yourself by defining
your own floating point type that has a String or Format method.
(See godoc fmt.)

Russ

Reply all
Reply to author
Forward
0 new messages