## digitalmars.D - integer division with float result

Stas Sergeev <stsp aknet.ru> writes:
Hi.

This is basically an out of curiosity.
I wonder how does D handle the integer division.
In C, as we all know, the following:
int a = 3;
int b = 5;
float c = a / b;
will give the result that will beat the ghost
out of any mathematician (unless you cast
one of the operands to float, of course).
I haven't used D yet, but I know that most
(or all?) of the C-unrelated languages do
that in a proper way, and even the Python
developers are going to fix that in the future.

So the question is: how does D handle that?
Was it infected by the Cish way of handling
an integer division (if so - why?), or managed
to get rid of that legacy thingy?

Nov 18 2007
Jason House <jason.james.house gmail.com> writes:
Stas Sergeev wrote:

Hi.

This is basically an out of curiosity.
I wonder how does D handle the integer division.
In C, as we all know, the following:
int a = 3;
int b = 5;
float c = a / b;
will give the result that will beat the ghost
out of any mathematician (unless you cast
one of the operands to float, of course).

Curiously enough, I hit this very bug rather
recently with D 1.x code.  I'm ashamed to say
that I hit it twice.

So the question is: how does D handle that?

It silent does what I suspect you fear it would do.

Nov 18 2007
Lars Noschinski <lars-2006-1 usenet.noschinski.de> writes:
* Stas Sergeev <stsp aknet.ru> [07-11-18 22:10]:
I haven't used D yet, but I know that most
(or all?) of the C-unrelated languages do
that in a proper way, and even the Python
developers are going to fix that in the future.

Which languages do that (without having a separate operator for integer
division)?

Nov 18 2007
Derek Parnell <derek nomail.afraid.org> writes:
On Sun, 18 Nov 2007 23:40:52 +0000 (UTC), Lars Noschinski wrote:

* Stas Sergeev <stsp aknet.ru> [07-11-18 22:10]:
I haven't used D yet, but I know that most
(or all?) of the C-unrelated languages do
that in a proper way, and even the Python
developers are going to fix that in the future.

Which languages do that (without having a separate operator for integer
division)?

Euphoria does. In fact it can be a bit of a nuisance at times.

int a,b,c
a = 3
b = 4
c = a / b -- Fails 'cos result is a floating number and you can't assign it
to an integer.
c = floor(a / b) -- Okay now.

--
Derek
(skype: derek.j.parnell)
Melbourne, Australia
19/11/2007 6:08:19 PM

Nov 18 2007
On 11/18/07, Lars Noschinski <lars-2006-1 usenet.noschinski.de> wrote:
* Stas Sergeev <stsp aknet.ru> [07-11-18 22:10]:
I haven't used D yet, but I know that most
(or all?) of the C-unrelated languages do
that in a proper way, and even the Python
developers are going to fix that in the future.

Which languages do that (without having a separate operator for integer
division)?

PHP does. But then, PHP doesn't have statically typed variables, so
maybe that doesn't count.

Nov 18 2007
Bill Baxter <dnewsgroup billbaxter.com> writes:
Stas Sergeev wrote:
Hi.

This is basically an out of curiosity.
I wonder how does D handle the integer division.
In C, as we all know, the following:
int a = 3;
int b = 5;
float c = a / b;
will give the result that will beat the ghost
out of any mathematician (unless you cast
one of the operands to float, of course).
I haven't used D yet, but I know that most
(or all?) of the C-unrelated languages do
that in a proper way, and even the Python
developers are going to fix that in the future.

So the question is: how does D handle that?
Was it infected by the Cish way of handling
an integer division (if so - why?), or managed
to get rid of that legacy thingy?

Comparing with dynamically typed languages like Python isn't useful
because in Python a/2 can return an integer for if a==4 a float if a==5.
A statically typed language like D doesn't have that luxury.

Anyway, that said, I think it'd be nice to have / do float division, and
introduce another operator (like python's //) for truncated integer
division.  But I think Walter is too entrenched in C-ish ways to see any
value in changing how it works.  Python is changing because it wants to
be newbie/scientist friendly above all else.  D merely wants to be
easier to use than C++.  There's a lot of territory between
"newbie-friendy" and "easier than C++".  In particular "has pointers"
and "newbie-friendly" tend to keep their distance from one another.

--bb

Nov 18 2007
Bill Baxter Wrote:

Stas Sergeev wrote:
Hi.

This is basically an out of curiosity.
I wonder how does D handle the integer division.
In C, as we all know, the following:
int a = 3;
int b = 5;
float c = a / b;
will give the result that will beat the ghost
out of any mathematician (unless you cast
one of the operands to float, of course).
I haven't used D yet, but I know that most
(or all?) of the C-unrelated languages do
that in a proper way, and even the Python
developers are going to fix that in the future.

So the question is: how does D handle that?
Was it infected by the Cish way of handling
an integer division (if so - why?), or managed
to get rid of that legacy thingy?

Comparing with dynamically typed languages like Python isn't useful
because in Python a/2 can return an integer for if a==4 a float if a==5.
A statically typed language like D doesn't have that luxury.

Anyway, that said, I think it'd be nice to have / do float division, and
introduce another operator (like python's //) for truncated integer
division.  But I think Walter is too entrenched in C-ish ways to see any
value in changing how it works.  Python is changing because it wants to
be newbie/scientist friendly above all else.  D merely wants to be
easier to use than C++.  There's a lot of territory between
"newbie-friendy" and "easier than C++".  In particular "has pointers"
and "newbie-friendly" tend to keep their distance from one another.

--bb

strongly typed language its only convention that makes the return type somehow
special.
I believe the original reason for return values being special may have been
that they are the only things left on the stack when returning from a function
call. This was only true early on when all arguments were passed by value.
We don't seem to have moved beyond that, we only tease around the edges with
covariant returns and returning multiple values but semantically there's no
difference between:

void divide(in T numerator, in T denominator, out T result)

and

T divide(in T numerator, in T denominator)

where T = any numeric type

So why do we still insist on it in modern languages?

Regards,

Bruce.

Nov 18 2007
0ffh <frank frankhirsch.youknow.what.todo.net> writes:
Bruce Adams wrote:
Bill Baxter Wrote:
Stas Sergeev wrote:
Hi. [...] So the question is: how does D handle that? Was it
infected by the Cish way of handling an integer division (if so -
why?), or managed to get rid of that legacy thingy?

It's a legacy think, yup! But not everything that is old is bad...
the rules didn't evolve like that for no reason.

Comparing with dynamically typed languages like Python isn't useful
because in Python a/2 can return an integer for if a==4 a float if
a==5. A statically typed language like D doesn't have that luxury.

Anyway, that said, I think it'd be nice to have / do float division,
and introduce another operator (like python's //) for truncated
integer division.  But I think Walter is too entrenched in C-ish ways
to see any value in changing how it works.  Python is changing because
it wants to be newbie/scientist friendly above all else.  D merely
wants to be easier to use than C++.  There's a lot of territory
between "newbie-friendy" and "easier than C++".  In particular "has
pointers" and "newbie-friendly" tend to keep their distance from one
another.

--bb

type? In a strongly typed language its only convention that makes the
return type somehow special. I believe the original reason for return
values being special may have been that they are the only things left on
the stack when returning from a function call. This was only true early
on when all arguments were passed by value. We don't seem to have moved
beyond that, we only tease around the edges with covariant returns and
returning multiple values but semantically there's no difference
between: [...] So why do we still insist on it in modern languages?

Regards,

Bruce.

Return type overloading is not practical, or at least not without solving a
few problems first. What return type would you expect from the function?
Okay, in an assignment it's clear.
What about function calls in expressions?
What if you have overloaded foo to return int or float, and bar to return
int or float. Then go and call bar(foo())... oooopsie! =)
And it's not always as easy as just int or float; think arbitrary types!
Okay, there are solutions to all this, but the only reasonable ones I
know need extra hints for the compiler (some kind of syntax extension,
or building a new semantic upon an available syntax).

Regards, Frank

Nov 18 2007
0ffh <frank frankhirsch.youknow.what.todo.net> writes:
0ffh wrote:
What if you have overloaded foo to return int or float, and bar to return
int or float. Then go and call bar(foo())... oooopsie! =)

Ooopsie, I meant "bar to /take/ int or float"...
take a laugh on me, everyone who spottet it! ;-)

Regards, frank

Nov 18 2007
Lionello Lunesu <lio lunesu.remove.com> writes:
 void divide(in T numerator, in T denominator, out T result)

and

T divide(in T numerator, in T denominator)

where T = any numeric type

So why do we still insist on it in modern languages?

Have to agree with Bruce on this one.

In fact, perhaps D could do something similar to that array trick (void
bla(T[]); T[] ar; ar.bla;) for the return value of a function: void
bla(out T); T t = bla;

(Isn't that similar to what the return value optimization does, by the way?)

L.

Nov 19 2007
renoX <renosky free.fr> writes:
Stas Sergeev a écrit :
Hi.

This is basically an out of curiosity.
I wonder how does D handle the integer division.
In C, as we all know, the following:
int a = 3;
int b = 5;
float c = a / b;
will give the result that will beat the ghost
out of any mathematician (unless you cast
one of the operands to float, of course).

Yep, this is a trap which catch probably all C beginners.

I haven't used D yet, but I know that most
(or all?) of the C-unrelated languages do
that in a proper way, and even the Python
developers are going to fix that in the future.

So the question is: how does D handle that?
Was it infected by the Cish way of handling
an integer division (if so - why?), or managed
to get rid of that legacy thingy?

In a statically typed language, the issue is which float type do you use
for (int / int)?
For accuracy, it ought to be one with biggest precision, but it's also
the slowest, and can be non-portable (x86 has 80-bit float, other CPU do
not)

So I came to the conclusion so that maybe removing the / for int/int is
the only thing to do as it's too ambiguous..
Instead using operators like idiv, fdiv, f64div may be a solution.

renoX

Nov 19 2007
Stas Sergeev <stsp aknet.ru> writes:
renoX Wrote:
In a statically typed language, the issue is which float type do you use
for (int / int)?
For accuracy, it ought to be one with biggest precision, but it's also
the slowest, and can be non-portable (x86 has 80-bit float, other CPU do
not)

For example, doing an integer calculus, you can
get an overflow, because the compiler does not
promote ints to long-longs for you. So if you have
a very large values, you have to explicitly notify
the compiler by doing casts. OTOH, it does promote
the shorts to ints for you, when needed.
Same is here: the float can be used by default, and
if you really need a hight precision, then you have
to resort to an explicit casts, I think.

Nov 19 2007
"David B. Held" <dheld codelogicconsulting.com> writes:
Stas Sergeev wrote:
renoX Wrote:
In a statically typed language, the issue is which float type do you use
for (int / int)?
For accuracy, it ought to be one with biggest precision, but it's also
the slowest, and can be non-portable (x86 has 80-bit float, other CPU do
not)

I don't think this is really a problem.
For example, doing an integer calculus, you can
get an overflow, because the compiler does not
promote ints to long-longs for you. So if you have
a very large values, you have to explicitly notify
the compiler by doing casts. OTOH, it does promote
the shorts to ints for you, when needed.
Same is here: the float can be used by default, and
if you really need a hight precision, then you have
to resort to an explicit casts, I think.

The main problem is that as much as we would like to idealize and
abstract away details about the representations of our numbers, that is
simply not practical, even on GFLOPS desktops.  We *do* have to know the
sizes of our numbers and whether they are integral or floating-point
types.  It matters a *lot* in almost every operation you perform.

From a number theory perspective ints and floats are a world apart.  It
is true that integers are not a field because they are not closed under
/.  However, that does not mean we should pretend that Z == R and force
float opDiv(int, int).  The reality is that int != Z, either.  No, int
== Z_2^32, and that *does* have a closed /, which makes it as much a
field as R, and deserving of its own int opDiv(int, int).  Of course,
the / defined on Z_n is different from int opDiv(int, int), but let us
not concern ourselves with that minor detail.

The fact of the matter is that computers are *not* Turing machines.
They have finite tapes, and the squares of those tapes have finite
sizes.  And the operation of these putative TMs are sensitive to the
size of the tape and the squares composing the tape.  No competent
programmer can ignore this reality.  We have overflow and underflow and
modular arithmetic on integral types.  That is fundamental to ALUs and
will remain so for the forseeable future.  Trying to hide these facts
from the user by defining float opDiv(int, int) is not doing her any
favors.  FP arithmetic is expensive, and using it should be explicit,
not implicit.

It's easy enough to define your own float div(int, int) function that
gives the desired behavior.  And if you are bothered that it doesn't
look like normal /, I would call that a feature and a benefit.

Dave

Nov 20 2007
Lars Noschinski <lars-2006-1 usenet.noschinski.de> writes:
* David B. Held <dheld codelogicconsulting.com> [07-11-20 10:31]:
From a number theory perspective ints and floats are a world apart.  It is true
that integers are not a field because they are not closed under /.  However,
that does not mean we should pretend that Z == R and force float opDiv(int,
int).  The reality is that int != Z, either.  No, int == Z_2^32, and that
*does* have a closed /, which makes it as much a field as R, and deserving of
its own int opDiv(int, int).  Of course, the / defined on Z_n is different from
int opDiv(int, int), but let us not concern ourselves with that minor detail.

Z_2^32 is not a field, and it has not got a division; e.g. 2^31 * z !=
1 for all z \in Z_2^32.

Nov 20 2007
"David B. Held" <dheld codelogicconsulting.com> writes:
Lars Noschinski wrote:
* David B. Held <dheld codelogicconsulting.com> [07-11-20 10:31]:
From a number theory perspective ints and floats are a world apart.
It is true that integers are not a field because they are not closed
under /.  However, that does not mean we should pretend that Z == R
and force float opDiv(int, int).  The reality is that int != Z,
either.  No, int == Z_2^32, and that *does* have a closed /, which
makes it as much a field as R, and deserving of its own int opDiv(int,
int).  Of course, the / defined on Z_n is different from int
opDiv(int, int), but let us not concern ourselves with that minor detail.

Z_2^32 is not a field, and it has not got a division; e.g. 2^31 * z !=
1 for all z \in Z_2^32.

Ah, Z_p is only a field when p is prime...yes, that's a noob error.  I
suspected as much, but I didn't work very hard to verify it.  Let's
discard one of the bit patterns and say that int == Z_2^32-1. ;)
Conceptually speaking, it's pretty close to true.

Dave

Nov 20 2007