## digitalmars.D - integer division with float result

• Stas Sergeev (18/18) Nov 18 2007 Hi.
• Jason House (5/17) Nov 18 2007 Curiously enough, I hit this very bug rather
• Lars Noschinski (3/7) Nov 18 2007 Which languages do that (without having a separate operator for integer
• Janice Caron (3/10) Nov 18 2007 PHP does. But then, PHP doesn't have statically typed variables, so
• Derek Parnell (13/21) Nov 18 2007 Euphoria does. In fact it can be a bit of a nuisance at times.
• Bill Baxter (13/33) Nov 18 2007 Comparing with dynamically typed languages like Python isn't useful
• 0ffh (14/48) Nov 18 2007 It's a legacy think, yup! But not everything that is old is bad...
• 0ffh (4/6) Nov 18 2007 Ooopsie, I meant "bar to /take/ int or float"...
• Lionello Lunesu (6/15) Nov 19 2007 Have to agree with Bruce on this one.
• Bruce Adams (36/65) Nov 18 2007 The obvious thing to do would be to require explict qualification when t...
• 0ffh (32/34) Nov 18 2007 Well, the use of a cast as hint for the compiler looks like a
• 0ffh (8/12) Nov 18 2007 Oops; this is with syntactic sugar, BTW, as I was
• Bruce Adams (2/45) Nov 18 2007 Well I wasn't advocating a change to D (yet). Hence the non D in my orig...
• 0ffh (10/25) Nov 18 2007 Far be it from me to add to the plethora of D feature requests, but
• 0ffh (6/7) Nov 18 2007 Nah, that's bull shite.
• Stas Sergeev (14/20) Nov 18 2007 Of course, but there is no problem to make the / op to
• Bill Baxter (6/23) Nov 18 2007 Which flavor of division is being used here?
• Lars Noschinski (4/10) Nov 19 2007 Efficiency and accuracy. An integer division is faster than a float
• Stas Sergeev (15/19) Nov 19 2007 But isn't it just an optimization issue? The compiler is supposed
• 0ffh (11/24) Nov 19 2007 No, exactly that is the problem: The compiler knows the result type
• Stas Sergeev (9/12) Nov 19 2007 I didn't think I was pressing it.
• 0ffh (21/33) Nov 19 2007 It's just that I can't stand the long threads which are usually
• 0ffh (7/9) Nov 19 2007 Hrmm, probably int division and two casts would suffice, which
• Matti Niemenmaa (4/5) Nov 20 2007 This actually isn't the case on Pentium 4, at least.
• 0ffh (4/8) Nov 20 2007 Even if fdiv takes as many cycles as idiv, you'll still
• Matti Niemenmaa (9/11) Nov 20 2007 True, there's some setup involved. I didn't check the code generated to ...
• bearophile (5/11) Nov 19 2007 Pascal uses / and div, and it's a good enough syntax.
• Stas Sergeev (5/11) Nov 19 2007 Well, in case / is made to return float, then the simplest
• renoX (11/30) Nov 19 2007 In a statically typed language, the issue is which float type do you use...
• Stas Sergeev (11/16) Nov 19 2007 I don't think this is really a problem.
• David B. Held (28/45) Nov 20 2007 The main problem is that as much as we would like to idealize and
• Lars Noschinski (3/10) Nov 20 2007 Z_2^32 is not a field, and it has not got a division; e.g. 2^31 * z !=
• David B. Held (6/18) Nov 20 2007 Ah, Z_p is only a field when p is prime...yes, that's a noob error. I
• Stas Sergeev (19/25) Nov 19 2007 I thought in cases where it doesn't, you would need an explicit
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
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
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
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
0ffh Wrote:

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

The obvious thing to do would be to require explict qualification when there is
an ambiguity. For everything else the types are sufficient cues.
I suspect what is required is type inference a la ML.
So in the case of
(in the following feel free to replace X with divde, Y with print and R with
random if that makes it easier to read).

int X(int a)
long X(long b)

void Y(int y)
void Y(long y)

void Z(int y)
void Q(long y)

int a = 1;
long b = 2;

Z(X(a)) is legal (no ambiguity)
Q(X(b)) is legal (no ambiguity)

Y(X(a))  - infer use of Y(int) because X(int) because a = int
Y(X(b)) - infer use of Y(long) because X(long) because b = long

The only place you have real ambiguity is:

int R(void)
long R(void)

so X(R()) is ambiguous and should thus cause a compile error.
It must be replaced with either:

int temp = R();
X(temp)

or X(cast(int)R())

This is trivial to implement in a compiler the type inference is a little more
tricky (though Walter did say he was interested in adding functional
programming features to D ;-).

I think a good syntactic sugar to use for that would be named parameters, which
are useful for so many other reasons (but much less trivial to implement)
So

Y(int Int)
Y(long Long)

would allow

X(Y(Int))

unfortunately this doesn't solve the problem for R because the return type
cannot be named
So casting cannot be eliminated entirely that way but it can be significantly
reduced. That's got to be a good thing surely?

Regards,

Bruce.

Nov 18 2007
0ffh <frank frankhirsch.youknow.what.todo.net> writes:
Bruce Adams wrote:
So casting cannot be eliminated entirely that way but it can be
significantly reduced. That's got to be a good thing surely?

Well, the use of a cast as hint for the compiler looks like a
rather nice choice. But then I don't quite see how it improves
the thing about integer and float division apart from the case
of assignments. Take:

void foo(int);
void foo(float);

As it is now, I have for example

int i,j;
float f;
[...]
i=i/j; // implicit int
f=cast(float)i/j; // explicit float
foo(i/j); // implicit int
foo(cast(float)i/j); // explicit float

int i,j;
float f;
[...]
i=i/j; // implicit int
f=i/j; // implicit float
foo(i/j); // compiler error: under-determined type information
foo(cast(int)i/j); // explicit int
foo(cast(float)i/j); // explicit float

So now there are just different cases where a cast is needed.
For some people I am sure the case with overloaded return types
has more appeal, but for others it is different. It's just a
matter of tastes, really, as the C way is no more complicated
than the other way. It is just not what many people expect at
first. I can't yet see how this small improvement is worth the
trouble implementing.

Regards, frank

Nov 18 2007
0ffh <frank frankhirsch.youknow.what.todo.net> writes:
0ffh wrote:
[...]
foo(cast(int)i/j); // explicit int
foo(cast(float)i/j); // explicit float

Oops; this is with syntactic sugar, BTW, as I was
just casting the first operand, not the expression.
Otherwise
foo(cast(int)(i/j)); // explicit int
foo(cast(float)(i/j)); // explicit float

(The current style example should work as it is.)

Regards, Frank

Nov 18 2007
0ffh Wrote:

So casting cannot be eliminated entirely that way but it can be
significantly reduced. That's got to be a good thing surely?

Well, the use of a cast as hint for the compiler looks like a
rather nice choice. But then I don't quite see how it improves
the thing about integer and float division apart from the case
of assignments. Take:

void foo(int);
void foo(float);

As it is now, I have for example

int i,j;
float f;
[...]
i=i/j; // implicit int
f=cast(float)i/j; // explicit float
foo(i/j); // implicit int
foo(cast(float)i/j); // explicit float

int i,j;
float f;
[...]
i=i/j; // implicit int
f=i/j; // implicit float
foo(i/j); // compiler error: under-determined type information
foo(cast(int)i/j); // explicit int
foo(cast(float)i/j); // explicit float

So now there are just different cases where a cast is needed.
For some people I am sure the case with overloaded return types
has more appeal, but for others it is different. It's just a
matter of tastes, really, as the C way is no more complicated
than the other way. It is just not what many people expect at
first. I can't yet see how this small improvement is worth the
trouble implementing.

Regards, frank

Well I wasn't advocating a change to D (yet). Hence the non D in my original
post. It was more a thought experiment. Your use case above is certainly a
compelling reason not to do it this way, at least for division. I wonder if
there is not a way of having the best of both worlds. Still, I begin to see why
others want a seperate div operator. I shall ponder some more...

Nov 18 2007
0ffh <frank frankhirsch.youknow.what.todo.net> writes:
Bruce Adams wrote:
0ffh Wrote:

int i,j; float f; [...] i=i/j; // implicit int f=i/j; // implicit
float foo(i/j); // compiler error: under-determined type information
foo(cast(int)i/j); // explicit  int
foo(cast(float)i/j); // explicit float
[...btw. thunderbird rewrapping does strange things to those lines...]

Well I wasn't advocating a change to D (yet). Hence the non D in my
original post. It was more a thought experiment. Your use case above is
certainly a compelling reason not to do it this way, at least for
division. I wonder if there is not a way of having the best of both
worlds. Still, I begin to see why others want a seperate div operator.
I shall ponder some more...

Far be it from me to add to the plethora of D feature requests, but
one possible solution might be giving an explicit precedence hierarchy
to the compiler at one point, e.g.

void foo(int){...}
void foo(float){...}
precedence foo(float) > foo(int);

could in case of ambiguity choose float over int.
But I'm not quite sure this could not backfire in some way...

Regards, frank

Nov 18 2007
0ffh <frank frankhirsch.youknow.what.todo.net> writes:
0ffh wrote:
precedence foo(float) > foo(int);

Nah, that's bull shite.

precedence float opDiv(int,int) > int opDiv(int,int);

Good thing is, in my code I could adhere to the classic way. =)

regards, frank (sleepy)

Nov 18 2007
Stas Sergeev <stsp aknet.ru> writes:
Bill Baxter Wrote:
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.

Of course, but there is no problem to make the / op to
just always return float, or is there?

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.

For what?
You either write:
int c = a / b;
or:
float c = a / b;
Both seem to perfectly express the intention, so
what is the new operator may be good for?
Currently, the later expression simply makes no
sense. I don't even think it is present in some code.
So I don't think there will be any confusion or the
compatibility breakage even.

Nov 18 2007
Bill Baxter <dnewsgroup billbaxter.com> writes:
Stas Sergeev wrote:
Bill Baxter Wrote:
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.

Of course, but there is no problem to make the / op to
just always return float, or is there?

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.

For what?
You either write:
int c = a / b;
or:
float c = a / b;
Both seem to perfectly express the intention, so
what is the new operator may be good for?

Which flavor of division is being used here?

void do_something(int x) { ... }
void do_something(float x) { ... }

do_something(a/b);

--bb

Nov 18 2007
Lars Noschinski <lars-2006-1 usenet.noschinski.de> writes:
* Stas Sergeev <stsp aknet.ru> [07-11-19 06:46]:
Bill Baxter Wrote:
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.

Of course, but there is no problem to make the / op to
just always return float, or is there?

Efficiency and accuracy. An integer division is faster than a float
division. Also, not all integer values can be represented exactly as
floats.

Nov 19 2007
Stas Sergeev <stsp aknet.ru> writes:
Lars Noschinski Wrote:
Of course, but there is no problem to make the / op to
just always return float, or is there?

Efficiency and accuracy. An integer division is faster than a float
division.

But isn't it just an optimization issue? The compiler is supposed
to know the result type beforehand, is it not? It then
can decide whether it needs the float calculations or not.
And in a more complex cases, the one can hint the compiler
to not use float calculation by explicit casts to int, like this:
int a = (int)(b / c) * 500;
This expression can still be compiled without the fp math.
And the cast is not redundant here as it truncates the value,
and the programmer always knows when he needs to truncate
the value in his expression. He is unlikely to forget such a cast.
While currently the casts like this:
float a = (b / (float)c) * 500;
are used only to tell the compiler about the desired type, and
the programmer can easily forget to put one.

Nov 19 2007
0ffh <frank frankhirsch.youknow.what.todo.net> writes:
Stas Sergeev wrote:
But isn't it just an optimization issue? The compiler is supposed
to know the result type beforehand, is it not?

No, exactly that is the problem: The compiler knows the result type
only in some cases, as has been said twice now already.

And in a more complex cases, the one can hint the compiler
to not use float calculation by explicit casts to int, like this:
int a = (int)(b / c) * 500;
This expression can still be compiled without the fp math.
And the cast is not redundant here as it truncates the value,
and the programmer always knows when he needs to truncate
the value in his expression. He is unlikely to forget such a cast.
While currently the casts like this:
float a = (b / (float)c) * 500;
are used only to tell the compiler about the desired type, and
the programmer can easily forget to put one.

That tradeoff can be made. Some people might be more happy then.
Some will be less happy. A lot of work will have been caused for
little gain.
Also: We have all understood your point. Some think the same as you,
some different. As it's a matter of tastes, you won't achieve much
more if you keep pressing it. This is not like wooing a woman, where
you get extra points for perseverance.

Regards, frank

Nov 19 2007
Stas Sergeev <stsp aknet.ru> writes:
0ffh Wrote:
Also: We have all understood your point. Some think the same as you,
some different. As it's a matter of tastes, you won't achieve much
more if you keep pressing it.

I didn't think I was pressing it.
The guy said that the efficiency is the problem,
and I said that I don't think so (perhaps I was wrong,
but where is the pressure?).
For some reasons the thread got "split". The fragments
that  I've found quickly, I've looked through, the others
got slipped. :) (but search seems to help now)

Nov 19 2007
0ffh <frank frankhirsch.youknow.what.todo.net> writes:
Stas Sergeev wrote:
0ffh Wrote:
Also: We have all understood your point. Some think the same as you,
some different. As it's a matter of tastes, you won't achieve much
more if you keep pressing it.

I didn't think I was pressing it.

Maybe not, conceded.

The guy said that the efficiency is the problem,
and I said that I don't think so (perhaps I was wrong,
but where is the pressure?).
For some reasons the thread got "split". The fragments
that  I've found quickly, I've looked through, the others
got slipped. :) (but search seems to help now)

It's just that I can't stand the long threads which are usually
caused when people try to argue about things which boil down to
a mere matter of preference. Those disagreements cannot, and so
will not, be resolved with technical (or any other) arguments.
Even if one of the possibilities were really objectively better
that doesn't help much unless it's by a rather wide margin.
The less difference it makes, the more unlikely it is that it's
convincing, the longer and more painful it all gets.
I just wanted to stop this short... =)

Now to something completely different: The efficiency thing.

If I make returning floats the default for integer division
then it will make actual integer division slow (three casts
and the float division) unless you have the compiler do type
inference. Type inference is not always possible. That means
we still need casts (only in different places now) plus extra
logic in the compiler to achieve nothing more than changing
to a different default behaviour, which is a matter of taste.
Q.E.D.

regards, frank

Nov 19 2007
0ffh <frank frankhirsch.youknow.what.todo.net> writes:
0ffh wrote:
then it will make actual integer division slow (three casts
and the float division) unless you have the compiler do type

Hrmm, probably int division and two casts would suffice, which
might be reduced by the optimiser to just the division. Still,
this works only for for some cases and does not invalidate the
overall argument (bit like some kind of type inference through
the back door, with the same weakness).

regards, frank

Nov 19 2007
Lars Noschinski wrote:
An integer division is faster than a float division.

This actually isn't the case on Pentium 4, at least.

--
E-mail address: matti.niemenmaa+news, domain is iki (DOT) fi

Nov 20 2007
0ffh <frank frankhirsch.youknow.what.todo.net> writes:
Matti Niemenmaa wrote:
Lars Noschinski wrote:
An integer division is faster than a float division.

This actually isn't the case on Pentium 4, at least.

Even if fdiv takes as many cycles as idiv, you'll still
have to add the time needed for the necessary casts.

regards, frank

Nov 20 2007
0ffh wrote:
Even if fdiv takes as many cycles as idiv, you'll still
have to add the time needed for the necessary casts.

True, there's some setup involved. I didn't check the code generated to get the
exact values, but on the Pentium 4, for instance, the FDIV instruction actually
takes some 5-10 cycles _less_ than the DIV/IDIV instruction. (If anybody wants
to research, see http://www.agner.org/optimize/instruction_tables.pdf )

Just pointing something out. Lars's point about accuracy is more relevant than
efficiency, anyway.

--
E-mail address: matti.niemenmaa+news, domain is iki (DOT) fi

Nov 20 2007
bearophile <bearophileHUGS lycos.com> writes:
Bill Baxter:
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++.

Pascal uses / and div, and it's a good enough syntax.
(If operators get changed, then replacing && with and, || with or, etc (and
maybe even | with OR, & with AND, etc), may be newbie friendly too. Even Python
keeps those cryptic & | ~ ^ maybe because if you need them you can't be too
much newbie).

Bye,
bearophile

Nov 19 2007
Stas Sergeev <stsp aknet.ru> writes:
Bill Baxter Wrote:
Of course, but there is no problem to make the / op to
just always return float, or is there?

Which flavor of division is being used here?
void do_something(int x) { ... }
void do_something(float x) { ... }
do_something(a/b);

Well, in case / is made to return float, then the simplest
answer might be that it should use do_something(float x).
But my statement about the compatibility was wrong
of course...

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)

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.

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
Stas Sergeev <stsp aknet.ru> writes:
0ffh Wrote:
Hrmm, probably int division and two casts would suffice, which
might be reduced by the optimiser to just the division.

Yes, that's exactly what I thought was a possibility.

Still,
this works only for for some cases

I thought in cases where it doesn't, you would need an explicit
cast anyway. eg:
int a = (int)(b / c) * 500;
You either _need_ that cast, or you need the float math. Because
the result will be different.
Well, this example is probably naive, but I yet have to dig
this thread more to find the counter-examples.
the division operator, which is not my preference anyway.

unless you have the compiler do type
inference.

You know, all flavours of the optimization are taken for
granted these days. :) When I try to compile my programs
with the optimizer disabled, it usually became 3 times
bigger and basically stops working because it became
a CPU hog. :) (well, this is not about a PC progs, but about
the progs for MCUs, and this basically is not my fault but
gcc/avr-libc's one, but the fact is that the prog became
completely unusable without an optimization).

Nov 19 2007