[M3devel] integer division/mod questions?
Jay K
jay.krell at cornell.edu
Wed Jan 20 12:21:00 CET 2010
Only lately with C99.
Prior to that it was unspecified.
- Jay
From: hosking at cs.purdue.edu
Date: Wed, 20 Jan 2010 05:09:33 -0500
To: jay.krell at cornell.edu
CC: m3devel at elegosoft.com
Subject: Re: [M3devel] integer division/mod questions?
C specifies truncated division.
Antony Hosking | Associate Professor | Computer Science | Purdue University
305 N. University Street | West Lafayette | IN 47907 | USA
Office +1 765 494 6001 +1 765 494 6001 | Mobile +1 765 427 5484 +1 765 427 5484
On 19 Jan 2010, at 21:59, Jay K wrote:
That paper also suggests a more efficient algorithm we should probably adopt:
/* Floored division */
long divF( long D, long d )
{
long q = D/d;
long r = D%d;
if ((r> 0 && d < 0) || (r < 0 && d> 0)) q = q-1;
return q;
}
long modF( long D, long d )
{
long r = D%d;
if ((r> 0 && d < 0) || (r < 0 && d> 0)) r = r+d;
return r;
}
Though the condition should be perhaps the equivalent (r < 0) != (d < 0)
or (r < 0) ^ (d < 0)
We'd probably want to be sure the / followed by % got optimized into just one divide though.
or maybe what I have is fine.
As long as the inputs are the same sign, the current code does just one / or one %. It is only for mixed sign inputs that you need more care.
I am assuming C never "rounds", but either truncates or "floors".
e.g. 1/2 in the face of rounding is 1.
Integer division probably not a big concern anyway, esp. with any negative numbers. The main place I ever see division/mod used is hash tables, and the numbers are always positive (I rarely see negative numbers used anywhere in "systems" programming actually -- file sizes, array indices, array sizes..all positive; "math" needs floating point often...)
- Jay
----------------------------------------
From: jay.krell at cornell.edu
To: rodney_bates at lcwb.coop; m3devel at elegosoft.com
Date: Wed, 20 Jan 2010 02:45:43 +0000
Subject: Re: [M3devel] integer division/mod questions?
There is a positive zero and a negative zero, and which one you get
Rodney you reminded me of something I forgot to ask:
Is 0 div -1 = 0 or -1?
In particular, in floating point, 0 / -1 is presumably -0 and 0 / 1 is presumably +0. Modula-3 is specified as returning the largest integer not greater than the floating point result. So the question then is, is 0> -0? Or are they equal? Integer-wise, there is no -0.
If 0> -0, then 0 div -1 should equal -1 instead of 0.
My current code I believe returns 0 for 0 div anything.
And I believe "the mod formula" holds as correct, since my testing checks that. I'll have to double double check.
The previous code probably also but I'll have to double check.
The previous code isn't necessarily the definition of correct though, since it was pretty clearly wrong for some cases.
Which is imply the question: Everyone agrees with me that the previous code was wrong? In particular, for LONG_MIN div negative, it was giving negative results, but I believe the result should be positive. Mod had a similar problem.
Nice if anyone can reproduce the problem with K&R + long long as well.
I don't like making changes here without some kind of independent confirmation, though I'm also pretty sure of myself..a contradiction I realize.
The previous code and I believe the current code are inconsistent as to when it would "trap", depending on compiler and optimization level. I assume that is ok for now, though in future we might want to make it predictable and honor the FloatMode stuff, but until that time, "unpredictable" is ok.
In particular, LONG_MIN div or mod -1 can trap.
div clearly has little choice. Mod I have to think about -- mod should be zero, right? LONG_MIN "evenly" divides by -1, the answer can't be represented, but the remainder can (it is zero). So maybe we should special case that to ensure it doesn't trap.
(anywhere I say "LONG_MIN", INT64_MIN has similar problem)
- Jay
----------------------------------------
Date: Tue, 19 Jan 2010 18:39:22 -0600
From: rodney_bates at lcwb.coop
To: m3devel at elegosoft.com
Subject: Re: [M3devel] integer division/mod questions?
hendrik at topoi.pooq.com wrote:
On Sun, Jan 17, 2010 at 10:44:53AM +0000, Jay K wrote:
-2147483648 div 2147483647 ?
-2147483648 mod 2147483647 ?
quotient = -1, remainer = -1 seems reasonable.
2147483647 * -1 + -1 == -2147483648
There are two kinds of binary integer arithmetic -- two's complement
and one's complement. In my experience, two's complement machines tend
to have the remainder being the same sign as the dividend; one's
complement machines semm to have a remainder the same sign as the
divisor.
One's complement machines are all but extinct these days.
Tony, you were concerned about showing your age, but 20 years is but an
evening past. I remember programming ones-complement arithmetic
in assembly language, definitely more decades ago than two.
And that was not my first job.
There is a positive zero and a negative zero, and which one you get
can depend on the operation and operand values that produced the
result, so you have to check for both of them, often with two
separate conditional branches.
Anyone remember nines- or tens-complement arithmetic on decimal
machines? Electromechanical accounting machines?
However, Modula-3 specifies div as rounding down, so
-2147483648 div 2147483647 == -2
and then
http://www.modula3.com/cm3/doc/reference/arithmetic.html
The value x DIV y is the floor of
the quotient of x and y; that is, the maximum integer
not exceeding the real number z such that z * y = x.
For integers x and y, the value of x MOD y is
defined to be x - y * (x DIV y).
This means that for positive y, the value of x MOD y
lies in the interval [0 .. y-1], regardless of
the sign of x. For negative y, the value of
x MOD y lies in the interval [y+1 .. 0], regardless
of the sign of x.
And this is consistent with MOD producing a canonical representative of
an equivalence class modulo y. It's what's wanted for a lot of
algorithms. What it returns for negative y isn't as important, but
it is important to have positive MODuli for positive y no matter what
the sign of x is.
But it's not what most two's-complement processors produce naturally.
Having a MODulo operation that is mathematically well-behaved takes
extra effort on these machines.
And it's also important to have a remainder that corresponds to the
division operator. On two's complement machines you have to either
* use extra instructions to correct the result of the divide
instruction to correspond to the mathematically desirable MOD
operator, or
* Have a separate remainder operation that does correspond to
division.
On one's complement machines MOD will have the same effect as remainder.
On two's complement, different.
-- hendrik
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20100120/5060991a/attachment-0002.html>
More information about the M3devel
mailing list