Division with integers and their results

14,209 views
Skip to first unread message

OmarShariffDontLikeIt

unread,
Nov 15, 2012, 11:41:13 AM11/15/12
to golang-nuts
Please see the following example:

http://play.golang.org/p/ttgAHWu_Jq

Why is it that the value of res is exactly 0, rather than 0.3, which
is what I would expect given that res is a float? In fact, just to
make sure that the problem is not the format call:

http://play.golang.org/p/jQmTxUMAZ6

produces a similar result 0.000000, Why does go do this? I understand
that an integer can go into a float, and that a float cannot go into
an integer (not without truncating), but I don't understand why
arithmetic on two integers, which produces a float, can't go into a
float!

Am I missing something?

Cheers,
Ben

andrey mirtchovski

unread,
Nov 15, 2012, 11:48:06 AM11/15/12
to OmarShariffDontLikeIt, golang-nuts
> I don't understand why
> arithmetic on two integers, which produces a float, can't go into a
> float!

an operation of two integer constants does not produce a float. this
behaviour is described in the language specification:

http://golang.org/ref/spec#Constant_expressions

tomwilde

unread,
Nov 15, 2012, 11:56:07 AM11/15/12
to golan...@googlegroups.com, omarsharif...@gmail.com
I would presume the behavior is the same of C; as described in the following thread:

Miki Tebeka

unread,
Nov 15, 2012, 12:08:05 PM11/15/12
to golan...@googlegroups.com
What happens is that 3/10 is evaluated first. Since it's division between two integers, the result will be an integer.
Only after that, the result (which is already 0) is stored into the float variable.

Just add a dot and you'll be fine (this makes it a float division):
    res = 3/10.

Ian Lance Taylor

unread,
Nov 15, 2012, 2:07:43 PM11/15/12
to tomwilde, golan...@googlegroups.com, omarsharif...@gmail.com
On Thu, Nov 15, 2012 at 8:56 AM, tomwilde <sedevel...@gmail.com> wrote:
> I would presume the behavior is the same of C; as described in the following
> thread:

In the case the result is similar to C, but Go and C handle constants
quite differently. In C every constant has a type, and constant
arithmetic acts just like variables of that type, including implicit
type conversion and promotion. In Go constants are untyped by
default, and arithmetic on constants is untyped.

Ian

Thomas Bushnell, BSG

unread,
Nov 15, 2012, 2:37:58 PM11/15/12
to Ian Lance Taylor, tomwilde, golang-nuts, omarsharif...@gmail.com
Except that it's not. Constants in Go do have type, and numeric constants have four possible types, not one. The fact that the reference says they are "untyped constants" means not that they have no type, but that they have types from the set {rune, integer, floating-point, complex}, rather than the much larger (and extensible) set of types for variables.

The OP ran into trouble precisely because he wanted to think of numeric constants as truly untyped.

Most of the time the automatic promotion rule for constant expressions hides this complexity, and you can proceed as if numeric constants were just a single generic number type. For example, you can do this without difficulty:

const a = 1<<2.0

You can even do this:

const a = 1<<'a'

So it really is true that you can use any numeric constant where any numeric type is allowed in an expression, provided the value fits within the domain of the constant type needed. (So "const a=1<<2.2" does give an error.)

But the ugliest wart of C is that "/" is used for two entirely different operations, depending on the numeric type of the arguments. Pascal distinguishes "/" and "DIV", where the former is always proper rational division, and the latter is always integer division. Likewise Scheme distinguishes "/" and "quotient" (and helpfully provides both "remainder" and "modulo", instead of making you remember which one "%" means).

This wart is not so consequential in Go, because of the strict typing rules. It is a continual annoyance and source of bugs in C because of its interaction with the automatic type promotion rules. But it turns out that it comes up again in Go right here, where there are automatic promotion rules between constant types.

So you can't just think of "untyped numeric constant" as a single constant type, you have to keep track of the difference between "untyped rune constant", "untyped floating-point constant", "untyped integer constant", and "untyped complex constant", because for this one operation, the value you get depends on exactly which type of "untyped numeric constant" you have.

Thomas

Peter

unread,
Nov 15, 2012, 2:48:36 PM11/15/12
to golan...@googlegroups.com, tomwilde, omarsharif...@gmail.com
"In Go constants are untyped by default, and arithmetic on constants is untyped."

I'm not sure that's the best way of thinking about it. Go constants don't have types like "int32" or "float64" by default, but they do come in different "flavours": integer, floating-point, complex (not the official word, I don't think there is one).

Combining untyped constants yields untyped constants. The problem the OP was having was misunderstanding that an "integer literal" yields an integer constant, and dividing two integer constants yields another integer constant.

If one of the (untyped) constants had been a floating-point constant, the result would be floating-point, and the same for complex.

I'm not sure I've helped make it any clearer :(

tomwilde

unread,
Nov 15, 2012, 3:04:37 PM11/15/12
to golan...@googlegroups.com, Ian Lance Taylor, omarsharif...@gmail.com

the value you get depends on exactly which type of "untyped numeric constant" you have.

My brain hurt :P

In my very humble opinion as a big Go fan and advocate of its concepts I do have to say that OP's example surprised me since the lvalue had an explicit type.
As a method expecting time.Duration can be called with a constant (hence the constant being typed to time.Duration at compile time) I would have expected each constant on the right side of the expression to also be accordingly typed.

OmarShariffDontLikeIt

unread,
Nov 16, 2012, 4:28:54 AM11/16/12
to golang-nuts
Thanks everyone for your responses. Reading your various explanations
and reading the section of the Go Spec regarding this, it all makes
logical sense.However, coming from a language that doesn't do this
(PHP) you can see why this isn't intuitive at all.

Can I suggest that the Tour of Go deals with this counter intuitive
behaviour early? I know an awful lot of developers coming to Go from
dynamic laguages like PHP, Ruby etc; much more than C developers
moving to Go. (I showed this problem to a greybeard C hacker here at
work and he gave the exact response you guys gave "add a decimal point
when doing division").

Cheers!
Ben



Jan Mercl

unread,
Nov 16, 2012, 4:37:41 AM11/16/12
to OmarShariffDontLikeIt, golang-nuts
On Fri, Nov 16, 2012 at 10:28 AM, OmarShariffDontLikeIt
<omarsharif...@gmail.com> wrote:
> Thanks everyone for your responses. Reading your various explanations
> and reading the section of the Go Spec regarding this, it all makes
> logical sense.However, coming from a language that doesn't do this
> (PHP) you can see why this isn't intuitive at all.

I would not call expectations about some property of language A being
reproduced/available by/in language B "intuitive".

-j

Ben Davies

unread,
Nov 16, 2012, 7:57:00 AM11/16/12
to Jan Mercl, golang-nuts
true, but I would call division resulting in a number with a decimal
point being put into a gloat without truncating intuitive.
From: Jan Mercl
Sent: 16/11/2012 09:38
To: OmarShariffDontLikeIt
Cc: golang-nuts
Subject: Re: [go-nuts] Re: Division with integers and their results

Kevin Gillette

unread,
Nov 16, 2012, 8:42:07 AM11/16/12
to golan...@googlegroups.com, OmarShariffDontLikeIt

Job van der Zwan

unread,
Nov 16, 2012, 8:43:35 AM11/16/12
to golan...@googlegroups.com, OmarShariffDontLikeIt
Regardless, as it is the result of a specific design choice, it won't hurt to make this choice explicit in a tour that (among other things) was made to showcase Go's design decisions.

Jan Mercl

unread,
Nov 16, 2012, 8:57:57 AM11/16/12
to Kevin Gillette, golang-nuts, OmarShariffDontLikeIt
Please fill an issue about that example in specs and specs are in
contradiction, thank you.

-j

Michael Jones

unread,
Nov 16, 2012, 11:39:17 AM11/16/12
to Jan Mercl, Kevin Gillette, golang-nuts, OmarShariffDontLikeIt
Hey Ben in the Casbah, here is an example to test your new knowledge. Don't run it until you are certain what it will print!


-j

--





--
Michael T. Jones | Chief Technology Advocate  | m...@google.com |  +1 650-335-5765

Henrik Johansson

unread,
Nov 16, 2012, 11:52:18 AM11/16/12
to Michael Jones, golang-nuts, Kevin Gillette, Jan Mercl, OmarShariffDontLikeIt

Sneaky! :-)

--
 
 

Michael Jones

unread,
Nov 16, 2012, 6:00:57 PM11/16/12
to Kevin Gillette, golan...@googlegroups.com, OmarShariffDontLikeIt
Good find! The example is wrong.

On Fri, Nov 16, 2012 at 5:42 AM, Kevin Gillette <extempor...@gmail.com> wrote:
The behavior differs from one example in the spec at http://golang.org/ref/spec#Constant_expressions

--
 
 

andrey mirtchovski

unread,
Nov 16, 2012, 7:58:59 PM11/16/12
to Michael Jones, Kevin Gillette, golang-nuts, OmarShariffDontLikeIt
CL https://codereview.appspot.com/6782084/ fixes the spec.
> --
>
>

tomwilde

unread,
Nov 16, 2012, 8:22:34 PM11/16/12
to golan...@googlegroups.com, Michael Jones, Kevin Gillette, OmarShariffDontLikeIt
Shouldn't it be the other way around, though?

Changing the specification because the implementation has a bug according to it seems counter-productive.

Michael Jones

unread,
Nov 16, 2012, 8:30:44 PM11/16/12
to tomwilde, golan...@googlegroups.com, Kevin Gillette, OmarShariffDontLikeIt
neither the numerator nor denominator in the example are "forced" to be non-integer. when they are used in an operation alone you have two numeric values that have no reason not to be interpreted as integers, so the division is integer division. the result of that is assigned to the float AFTER the division. All the ways of coercion would work:

var n float64 = 2
n = n/3

that's 1.5

n := float64(2)/3

same.

n := 2.0/3 or n = 2/3.0

same.

Thomas Wilde

unread,
Nov 16, 2012, 8:42:24 PM11/16/12
to Michael Jones, golan...@googlegroups.com

Still, this is the detailed technical specification of how the language should work and behave, not a draft or other loosely formulated paper.

Someone wrote that line into the spec for a reason and with something in mind.

By the way; where is Russ? I think he would agree.

andrey mirtchovski

unread,
Nov 16, 2012, 8:51:05 PM11/16/12
to Thomas Wilde, Michael Jones, golang-nuts
the spec will most likely be changed.

https://codereview.appspot.com/6782084/
> --
>
>
Reply all
Reply to author
Forward
0 new messages