9

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.

mjv
  • 73,152
  • 14
  • 113
  • 156
user69514
  • 26,935
  • 59
  • 154
  • 188

6 Answers6

30

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

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • 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. –  Feb 02 '10 at 21:41
  • 1
    @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 Feb 02 '10 at 21:47
  • 1
    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 Feb 02 '10 at 21:48
  • @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. –  Feb 02 '10 at 22:02
  • 2
    This is true - it was implementation-defined in C89. – caf Feb 02 '10 at 23:01
  • @Steve: -5/2 = -2.5, which for integer division truncates the .5 leaving -2, making this answer completely correct. – Lawrence Dol Feb 02 '10 at 23:53
  • @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). –  Feb 03 '10 at 00:22
6

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
  • 776
  • 6
  • 15
  • 1
    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 Feb 02 '10 at 21:53
5

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
  • 769
  • 2
  • 10
  • 16
4

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
  • 422,506
  • 82
  • 585
  • 676
  • 6
    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. – C. K. Young Feb 02 '10 at 20:39
  • @Chris: yes, i just checked the exact rules. It's not soemthing I'd rely on day to day. Thanks – gbn Feb 02 '10 at 20:43
  • 1
    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 Feb 02 '10 at 20:45
  • @UncleBens: Why would it surprise you? – jarnbjo Feb 02 '10 at 21:10
  • @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 Feb 02 '10 at 21:45
  • @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 Feb 02 '10 at 21:50
  • 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. –  Feb 02 '10 at 23:29
2

this question was answered before on this site, you are doing an integer division, if you want to get the 0.5 use:

double x = (double)1/2;

and you will get the value of 0.5 .

Jorgesys
  • 124,308
  • 23
  • 334
  • 268
1

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.

  • 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 Feb 02 '10 at 21:56