views:

407

answers:

6

if I have something like:

long x = 1/2;

shouldn't this be rounded up to 1? When I print it on the screen it say 0.

+9  A: 

Look up: Integer division.

dirkgently
+24  A: 

It's doing integer division, which truncates everything to the right of the decimal point.

tvanfosson
That claim doesn't work if you're using C and you have negative numbers. From C++, I just got -5/2=-2 (rounding toward zero). If you check in twos complement, you'll see that that isn't simple truncation - that would give -5/2=-3. I suspect the C++ result is actually implementation defined.
Steve314
@Steve314: Yup. The C++ standard gives you that `(a / b) * b + a % b == a`, and assures you that if a and b are both positive, `a / b` and `a % b` will be nonnegative. If a and/or b are negative, the signs are implementation-defined (Standard, 5.6). I don't have the C or Java standard documents handy.
David Thornley
It's completely specified in C (and I imagine this is inherited by C++): `When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded.` (ie, it *is* truncation, but truncation defined with respect to the numerical value, not the underlying representation).
caf
@caf - if what you say is true, it's a recent standard defining what previous standards left undefined. The fact that it isn't currently defined in C++ is *because* it was undefined in C at the point when the standard was copied over.
Steve314
This is true - it was implementation-defined in C89.
caf
@Steve: -5/2 = -2.5, which for integer division truncates the .5 leaving -2, making this answer completely correct.
Software Monkey
@Monkey - that's not what happens when working in 2s complement. The current C standard probably makes the underlying representation irrelevant, but the current C++ standard and older C standards don't. When you do truncation in 2s complement binary, -5/2 = -3 (the actual binary steps are shown in my answer).
Steve314
+3  A: 

It can't round because it's never in a state to be rounded

The expression "1/2" is never 0.5 before assign to long

Now, long x = 1.0/2.0 because the expression on the right before assign is valid for rounding. Unless you get 0.499999999999997...

gbn
No, assigning a floating-point number to an integer _still_ truncates. Of course, the rest of your point, about how integer division never results in anything floating-point to begin with, is still valid.
Chris Jester-Young
@Chris: yes, i just checked the exact rules. It's not soemthing I'd rely on day to day. Thanks
gbn
I think you'd often see things like `long x = 1.0 / 2.0 + 0.5` I suppose even this won't help if you get 0.499999999999997... as the result (which would surprise me in this case very much), but if so, probably nothing helps, other than not rounding floats to integers.
UncleBens
@UncleBens: Why would it surprise you?
jarnbjo
@jambjo: Seeing that 1.0, 2.0 and 0.5 can all be represented exactly (with whatever the typical standard for floating-point is called), and that when tested the result is 1 as expected :) I'm not saying that it would work for all inputs, but if it doesn't I don't see a way how you could reliably round floats in the first place. (Basically, if it matters, one shouldn't use floats at all.)
UncleBens
@jambjo: It would surprise me because 0.5 is precisely representable in binary floating-point, and there's nothing fancy going on to get there. Something like `(1.0 / 6.0) * 3.0 + 0.5` is using numbers not precisely representable in binary, and then I wouldn't be surprised by an inexact answer.
David Thornley
This reminds me of an argument once when someone tried to tell me that something built faulty isn't broken because it was never working. Natural language just isn't that pedantic. Past participles are often used as adjectives, sometimes implying a past transition in state, but just as often only describing the current state. For a result to be rounded doesn't require that the machine must have generated an intermediate unrounded result.
Steve314
+3  A: 

What this expression is doing is it first declares the existence of a long called x, and then assigning it the value of the right hand side expression. The right hand side expression is 1/2, and since 1 and 2 are both integers this is interpreted as integer division. With integer division the result is always an Integer, so something along the lines of 5/3 will return 1, as only one three fits in a five. So with 1/2, how many 2s can fit into 1? 0.

This can in some languages result in some interesting outputs if you write something like double x = 1/2. You might expect 0.5 in this case, but it will often evaluate the integer value on the right first before assigning and converting the result into a double, giving the value 0.0

It is important to note that when doing this kind of type conversion, it will never round the result. So if you do the opposite: long x = (long)(1.0/2.0); then while (1.0/2.0) will evaluate to 0.5, the (long) cast will force this to be truncated to 0. Even if I had long x = (long)(0.9), the result will still be 0. It simply truncates after the decimal point.

Jacob Bellamy
+3  A: 

Integer division has its roots in number theory. When you do 1/2 you are asking how many times does 2 equal 1? The answer is never, so the equation becomes 0*2 + 1 = 1, where 0 is the quotient (what you get from 1/2) and 1 is the remainder (what you get from 1%2).

It is right to point out that % is not a true modulus in the mathematical sense but always a remainder from division. There is a difference when you are dealing with negative integers.

Hope that helps.

Johann Oskarsson
At least in C++ it can be a true modulus; that's implementation-defined. Face it, there is no way of handling integer division and remainders with negative numbers that everybody will find intuitive.
David Thornley
A: 

There are lots of different rounding conventions, the most common being rounding towards +inf, rounding towards -inf and rounding towards zero. Lots of people assume there's one right way, but they all have different ideas about what that one way should be ;-)

There is no intermediate non-integer result for integer division, but of course the division is done deterministically, and one particular rounding convention will always be followed for a particular platform and compiler.

With Visual C++ I get 5/2 = 2 and -5/2 = -2, rounding towards zero.

The rounding in C, C++ and Java is commonly called "truncation" - meaning drop off the unwanted bits. But this can be misleading. Using 4 bit 2s complement binary, doing what truncation implies gives...

 5/2 = 0101/0010 = 0010.1 --> 0010 =  2
-5/2 = 1011/0010 = 1101.1 --> 1101 = -3

Which is rounding towards -infinity, which is what Python does (or at least what it did in Python 2.5).

Truncation would be the right word if we used a sign-magnitude representation, but twos complement has been the de-facto standard for decades.

In C and C++, I expect while it's normally called truncation, in reality this detail is undefined in the standards and left to the implementation - an excuse for allowing the compiler to use the simplest and fastest method for the platform (what the processors division instruction naturally does). It's only an issue if you have negative numbers though - I've yet to see any language or implementation that would give 5/2 = 3.

I don't know what the Java standard says. The Python manual specifies "floor" division, which is a common term for rounding to -infinity.

EDIT

An extra note - by definition, if a/b = c remainder d, then a = (b*c)+d. For this to hold, you have to choose a remainder to suite your rounding convention.

People tend to assume that remainders and modulos are the same, but WRT signed values, they can be different - depending on the rounding rules. Modulo values are by definition never negative, but remainders can be negative.

I suspect the Python round-towards-negative-infinity rule is intended to ensure that the single % operator is valid both as a remainder and as a modulo. In C and C++, what % means (remainder or modulo) is (yes, you guessed it) implementation defined.

Ada actually has two separate operators - mod and rem. With division required to round towards zero, so that mod and rem do give different results.

Steve314
The C++ standard requires that, for positive ints a and b, `a % b` be nonnegative, so `5 / 3` couldn't possibly be 3, as then `5 % 3` would have to be -4. It recommends rounding the quotient towards zero with negative numbers, but that's implementation-defined.
David Thornley