C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Modulus operation on negative numbers
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Ganny
Guest





PostPosted: Tue Mar 07, 2006 12:06 pm    Post subject: Modulus operation on negative numbers Reply with quote



This is regarding the computation of modulus operation in C/C++ for
negative numbers. Irrespective of the value (positive or negative) of
the integer, C/C++ follows the rule "(a/b)*b + a%b shall equal a" (C99
- 6.5.5[6]). For negative numbers, it is different from the
mathematical interpretation of the modulus/remainder operation:

http://mathforum.org/library/drmath/view/52343.html

Probably, there should have been two operators, mod and div as in Ada:

http://archive.adaic.com/standards/83lrm/html/lrm-04-05.html

Does anybody know why it wasn't done (for C/C++)?

Thanks!
-Ganesh


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Rob
Guest





PostPosted: Wed Mar 08, 2006 1:06 am    Post subject: Re: Modulus operation on negative numbers Reply with quote



Ganny wrote:

Quote:
This is regarding the computation of modulus operation in C/C++ for
negative numbers. Irrespective of the value (positive or negative) of
the integer, C/C++ follows the rule "(a/b)*b + a%b shall equal a" (C99
- 6.5.5[6]). For negative numbers, it is different from the
mathematical interpretation of the modulus/remainder operation:

http://mathforum.org/library/drmath/view/52343.html

Probably, there should have been two operators, mod and div as in Ada:

http://archive.adaic.com/standards/83lrm/html/lrm-04-05.html

Does anybody know why it wasn't done (for C/C++)?



The way C (particularly up to and including the 1989 standard)
supported anything mathematical or numerical left a fair bit to be
desired. The support (other than some basic operations) was more an
afterthought than a carefully considered part of the language. The
rule you quote for the modulo operator is something that is more
convenient for compiler writers and computer scientists (it is a valid
operation with a clean definition) than it is concerned with being
mathematically correct.

So, to answer you question, it probably wasn't "done" for C/C++ because
it wasn't thought of, rather than because of a deliberate design
decision.

You will find that people who do a lot of mathematical work in C/C++
will often write a small math library to do the jobs required
(fortunately, although the language and library is mathematically
incorrect in a number of ways, it is not particularly difficult to
implement correct functions).

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Alberto Ganesh Barbati
Guest





PostPosted: Wed Mar 08, 2006 1:06 am    Post subject: Re: Modulus operation on negative numbers Reply with quote



Ganny ha scritto:
Quote:
This is regarding the computation of modulus operation in C/C++ for
negative numbers. Irrespective of the value (positive or negative) of
the integer, C/C++ follows the rule "(a/b)*b + a%b shall equal a" (C99
- 6.5.5[6]). For negative numbers, it is different from the
mathematical interpretation of the modulus/remainder operation:

http://mathforum.org/library/drmath/view/52343.html

In fact in the C Standard the operator % is always called "remainder"
and never "modulus". The C++ standard makes a bit of confusion, because
§5.6 uses the word "remainder" but in the index the word "modulus" is
used instead. It's worth mentioning that there exist a std::modulus
functor in the standard library that computes a%b. It should have been
called std::remainder, IMHO.

Quote:
Probably, there should have been two operators, mod and div as in Ada:

http://archive.adaic.com/standards/83lrm/html/lrm-04-05.html

(I guess you meant rem and mod). Probably. I guess it's too late to add
it now... We have to stick to a library-based solution, I suppose.

Quote:
Does anybody know why it wasn't done (for C/C++)?

No idea...

Ganesh

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Jack Klein
Guest





PostPosted: Wed Mar 08, 2006 10:06 am    Post subject: Re: Modulus operation on negative numbers Reply with quote

On 7 Mar 2006 06:56:27 -0500, "Ganny" <sgganesh (AT) gmail (DOT) com> wrote in
comp.lang.c++.moderated:

Quote:
This is regarding the computation of modulus operation in C/C++ for
negative numbers. Irrespective of the value (positive or negative) of
the integer, C/C++ follows the rule "(a/b)*b + a%b shall equal a" (C99
- 6.5.5[6]). For negative numbers, it is different from the
mathematical interpretation of the modulus/remainder operation:

http://mathforum.org/library/drmath/view/52343.html

Probably, there should have been two operators, mod and div as in Ada:

http://archive.adaic.com/standards/83lrm/html/lrm-04-05.html

Does anybody know why it wasn't done (for C/C++)?

Thanks!
-Ganesh

There is no language C/C++.

C++ adopted the original C specification, as has been pointed out. In
1999 C changed that, C++ may or may not decide to do the same in a few
years.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
John G Harris
Guest





PostPosted: Thu Mar 09, 2006 11:06 am    Post subject: Re: Modulus operation on negative numbers Reply with quote

In message <1141705516.093941.74740 (AT) p10g2000cwp (DOT) googlegroups.com>, Ganny
<sgganesh (AT) gmail (DOT) com> writes
Quote:
This is regarding the computation of modulus operation in C/C++ for
negative numbers. Irrespective of the value (positive or negative) of
the integer, C/C++ follows the rule "(a/b)*b + a%b shall equal a" (C99
- 6.5.5[6]). For negative numbers, it is different from the
mathematical interpretation of the modulus/remainder operation:

http://mathforum.org/library/drmath/view/52343.html

Probably, there should have been two operators, mod and div as in Ada:

http://archive.adaic.com/standards/83lrm/html/lrm-04-05.html

Does anybody know why it wasn't done (for C/C++)?

For integers the equation
a = q*b + r
has an infinite number of solutions. Even if you want r to be close to
zero (and b non-zero) there are several reasonable solutions. One will
be right for your project, one will be right for mine, and neither will
be right for someone else. It doesn't matter what rule for / and % the
standard defines : it is going to be 'right' in some contexts and wrong
in others.

As for modulus, you might think that mod 12 should give a number in the
range 0..11, but then you look at a few clocks and see that many people
prefer 1..12. Again it's a matter of which definition is more
appropriate in which context.

John
--
John Harris

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Thant Tessman
Guest





PostPosted: Thu Mar 09, 2006 7:06 pm    Post subject: Re: Modulus operation on negative numbers Reply with quote

John G Harris wrote:

Quote:
For integers the equation
a = q*b + r
has an infinite number of solutions. Even if you want r to be close to
zero (and b non-zero) there are several reasonable solutions. One will
be right for your project, one will be right for mine, and neither will
be right for someone else. It doesn't matter what rule for / and % the
standard defines : it is going to be 'right' in some contexts and wrong
in others.

So describe for us a problem for which the solution typically chosen by
hardware implementors is the 'right' solution (beyond the case where a,
b, and r are all positive that is).

[...]

-thant

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
John G Harris
Guest





PostPosted: Sat Mar 11, 2006 2:06 pm    Post subject: Re: Modulus operation on negative numbers Reply with quote

In message <dupn5j$r5g$1 (AT) news (DOT) xmission.com>, Thant Tessman
<adm (AT) standarddeviance (DOT) com> writes
Quote:
John G Harris wrote:

For integers the equation
a = q*b + r
has an infinite number of solutions. Even if you want r to be close to
zero (and b non-zero) there are several reasonable solutions. One will
be right for your project, one will be right for mine, and neither will
be right for someone else. It doesn't matter what rule for / and % the
standard defines : it is going to be 'right' in some contexts and wrong
in others.

So describe for us a problem for which the solution typically chosen by
hardware implementors is the 'right' solution (beyond the case where a,
b, and r are all positive that is).

As a one-time mainframe designer I think I can give an honest answer to
that. The hardware is designed to go as fast as possible without adding
extra clock cycles and extra hardware for uninteresting cases. The
result is that negative numbers do whatever they do. If you're lucky q
and r are always coherent. If you're *very* lucky the rules are
documented accurately, but I wouldn't want to bet on it.

Sometimes there are explicit requirements aimed at facilitating
multi-word arithmetic. In that case you are at the mercy of the
specifier, right or wrong.

John
--
John Harris

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Thant Tessman
Guest





PostPosted: Sat Mar 11, 2006 6:06 pm    Post subject: Re: Modulus operation on negative numbers Reply with quote

[...deliberately leaving much quoted material...]

John G Harris wrote:

Quote:
In message <dupn5j$r5g$1 (AT) news (DOT) xmission.com>, Thant Tessman
adm (AT) standarddeviance (DOT) com> writes

John G Harris wrote:


For integers the equation
a = q*b + r
has an infinite number of solutions. Even if you want r to be close to
zero (and b non-zero) there are several reasonable solutions. One will
be right for your project, one will be right for mine, and neither will
be right for someone else. It doesn't matter what rule for / and % the
standard defines : it is going to be 'right' in some contexts and wrong
in others.

So describe for us a problem for which the solution typically chosen by
hardware implementors is the 'right' solution (beyond the case where a,
b, and r are all positive that is).


As a one-time mainframe designer I think I can give an honest answer to
that. The hardware is designed to go as fast as possible without adding
extra clock cycles and extra hardware for uninteresting cases. The
result is that negative numbers do whatever they do. If you're lucky q
and r are always coherent. If you're *very* lucky the rules are
documented accurately, but I wouldn't want to bet on it.

Given that so many other languages provide functions that deliberately
don't match the behavior of '/' and '%' in the "uninteresting" cases, it
might be that they're not so uninteresting after all.

To elaborate for other readers, the "correct" behavior is for the sign
of the remainder to match the sign of the denominator. This is (almost?)
always the behavior you want when you're doing real math. Hardware
typically makes the sign of the remainder match the sign of the
numerator, which is (almost?) always an outright bug in the case where
the numerator and denominator aren't expected to be always positive.

inline div_t divmod(int n, int d) {

div_t qr = div(n, d);

if ((qr.rem<0 && d>0) ||
(qr.rem>0 && d<0)) {
--qr.quot;
qr.rem += d;
}

return qr;
}

-thant

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
John G Harris
Guest





PostPosted: Sun Mar 12, 2006 9:06 am    Post subject: Re: Modulus operation on negative numbers Reply with quote

In message <duupgh$9e0$1 (AT) news (DOT) xmission.com>, Thant Tessman
<adm (AT) standarddeviance (DOT) com> writes

To recap, a = q*b + r

<snip>
Quote:
To elaborate for other readers, the "correct" behavior is for the sign
of the remainder to match the sign of the denominator. This is (almost?)
always the behavior you want when you're doing real math. Hardware
typically makes the sign of the remainder match the sign of the
numerator, which is (almost?) always an outright bug in the case where
the numerator and denominator aren't expected to be always positive.
snip


When a, b are non-negative and b non-zero the C++ standard requires that
0 <= r < b .
We are both happy about this case.

In other cases, with b non-zero, the standard allows any answer provided
-abs(b) <= r <= abs(b)
(though it's not said as clearly as that).

When a is negative and b is positive you want
0 <= r < b .

Unfortunately for you, footnote 74 of the standard says

"According to work underway toward the revision of ISO C, the preferred
algorithm for integer division follows the rules defined in
the ISO Fortran standard, ISO/IEC 1539:1991, in which the quotient is
always rounded toward zero."

This means that when a is negative and b is positive you might one day
get
-abs(b) < r <= 0
because this make a negative quotient more positive, so closer to zero.

This is the opposite of what you would like. Any comments ?

John
--
John Harris

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Alberto Ganesh Barbati
Guest





PostPosted: Sun Mar 12, 2006 4:06 pm    Post subject: Re: Modulus operation on negative numbers Reply with quote

Thant Tessman ha scritto:
Quote:

To elaborate for other readers, the "correct" behavior is for the sign
of the remainder to match the sign of the denominator. This is (almost?)
always the behavior you want when you're doing real math. Hardware
typically makes the sign of the remainder match the sign of the
numerator, which is (almost?) always an outright bug in the case where
the numerator and denominator aren't expected to be always positive.


The remainder operation is strictly tied to the division operation. Your
behavior is equivalent to saying that the result of the division is to
be rounded towards minus infinity, so while it gives "correct" results
for the remainders (according to some definition of "correct"), it gives
"wrong" (according to some definition of "wrong") results for the
division. For example, with your behavior:

6 / 5 = 1 * 5 + 1
6 / -5 = -2 * -5 - 4
-6 / 5 = -2 * 5 + 4
-6 / -5 = 1 * -5 - 1

Some people finds that (-a/b) != -(a/b) is not "correct". You might
disagree, but they have their reasons.

With the rounding-towards-zero approach, the results would be:

6 / 5 = 1 * 5 + 1
6 / -5 = -1 * -5 + 1
-6 / 5 = -1 * 5 - 1
-6 / -5 = 1 * -5 - 1

I don't think there really is a "mathematically correct" behavior among
the two, but, if I had to choose, I'd choose the latter. It seems that
I'm not the only one that shares this opinion, as the ISO Fortran
standard (ISO/IEC 1539:1991) specifically chooses the
rounding-towards-zero approach and the C standard adopted this decision
in its latest revision (ISO/IEC 9899:1999). According to the footnote to
5.6/4 in the C++ standard, it seems quite probable that the next
revision of C++ will also follow this route.

Regards,

Ganesh

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Thant Tessman
Guest





PostPosted: Sun Mar 12, 2006 6:06 pm    Post subject: Re: Modulus operation on negative numbers Reply with quote

John G Harris wrote:

[...]

Quote:
Unfortunately for you, footnote 74 of the standard says

"According to work underway toward the revision of ISO C, the preferred
algorithm for integer division follows the rules defined in
the ISO Fortran standard, ISO/IEC 1539:1991, in which the quotient is
always rounded toward zero."

This means that when a is negative and b is positive you might one day
get
-abs(b) < r <= 0
because this make a negative quotient more positive, so closer to zero.

This is the opposite of what you would like. Any comments ?

A couple of languages with which I'm familiar provide both the "correct"
version, and the "fast" version. The "fast" version doesn't promise to
round toward zero. It merely promises to match the behavior of the
hardware--which usually rounds toward zero.

Clearly the designers of these other languages don't value the promise
of a consistently incorrect answer. They apparently merely want to take
into account that people sometimes might value the performance of the
"fast" version in the use cases where the "fast" version can be trusted.

-thant

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Andrei Alexandrescu (See
Guest





PostPosted: Mon Mar 13, 2006 10:06 am    Post subject: Re: Modulus operation on negative numbers Reply with quote

Thant Tessman wrote:
Quote:
John G Harris wrote:

[...]


Unfortunately for you, footnote 74 of the standard says

"According to work underway toward the revision of ISO C, the preferred
algorithm for integer division follows the rules defined in
the ISO Fortran standard, ISO/IEC 1539:1991, in which the quotient is
always rounded toward zero."

This means that when a is negative and b is positive you might one day
get
-abs(b) < r <= 0
because this make a negative quotient more positive, so closer to zero.

This is the opposite of what you would like. Any comments ?


A couple of languages with which I'm familiar provide both the "correct"
version, and the "fast" version. The "fast" version doesn't promise to
round toward zero. It merely promises to match the behavior of the
hardware--which usually rounds toward zero.

Clearly the designers of these other languages don't value the promise
of a consistently incorrect answer. They apparently merely want to take
into account that people sometimes might value the performance of the
"fast" version in the use cases where the "fast" version can be trusted.

One thing I never understood was why the heck they turned the problem on
its head. So they say: "We give you a correct version with predictable
behavior, and whatever the hardware does."

Given that there are two choices anyway (round towards zero or towards
infinity), why in the world don't they give you the two versions, both
with predictable behavior, and let you choose the one that you need?
Then, if the machine happens to implement what you needed, it's fast. If
not, it's slower but you needed that behavior anyway.

I must be missing something.


Andrei

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Thant Tessman
Guest





PostPosted: Mon Mar 13, 2006 10:06 am    Post subject: Re: Modulus operation on negative numbers Reply with quote

Alberto Ganesh Barbati wrote:

[...]

Quote:
Some people finds that (-a/b) != -(a/b) is not "correct". You might
disagree, but they have their reasons. [...]

Okay, who are they, and what are their reasons?

That's the problem. People simply assume that there's a reason these
functions behave the way they do, but no one seems to know what it is
(beyond being easier to implement in hardware).



-thant


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
John G Harris
Guest





PostPosted: Tue Mar 14, 2006 12:06 am    Post subject: Re: Modulus operation on negative numbers Reply with quote

In message <4414612E.9040505 (AT) erdani (DOT) org>, "Andrei Alexandrescu (See
Website For Email)" <SeeWebsiteForEmail (AT) erdani (DOT) org> writes

Recap : a = q*b + r

<snip>
Quote:
Given that there are two choices anyway (round towards zero or towards
infinity), why in the world don't they give you the two versions, both
with predictable behavior, and let you choose the one that you need?
Then, if the machine happens to implement what you needed, it's fast. If
not, it's slower but you needed that behavior anyway.

I must be missing something.
snip


That's the problem with this subject; it's nearly as emotional as GC :-)

There are more than two reasonable specs for (q,r). Which is most
appropriate depends on the application domain : modulo arithmetic, paper
and pencil simulation, general financial, fixed point banking
arithmetic, to name a few.

As it happens, both of the two rules you quote have been flagged as
wrong by Thant.

John
--
John Harris

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Alberto Ganesh Barbati
Guest





PostPosted: Wed Mar 15, 2006 11:06 am    Post subject: Re: Modulus operation on negative numbers Reply with quote

Thant Tessman ha scritto:
Quote:
Alberto Ganesh Barbati wrote:

[...]

Some people finds that (-a/b) != -(a/b) is not "correct". You might
disagree, but they have their reasons. [...]

Okay, who are they, and what are their reasons?

For example the people of the Fortran committee (or at least the
majority of them) that approved in 1991 the ISO Fortran Standard. For
example the people of C committee (or at least the majority of them)
that approved in 1998 the C standard. It seems a bunch of very
representative people to me. The reasons? You ask them.

Quote:
That's the problem. People simply assume that there's a reason these
functions behave the way they do, but no one seems to know what it is
(beyond being easier to implement in hardware).

That's the problem. People simply assume that they are the first ones in
the history of computer science to think about a problem. People don't
realize that the problem might have been discussed ad nauseam in 1991
(well... most probably long before, since Fortran dates back to the
'50). People don't think that this kind of things do not "happen"
spontaneously but decisions were made and there were rationales behind
them. Even the QWERTY layout has a rationale behind it! (Although very
objectionable in this case... ;)

Do you realize that maybe rounding-toward-zero is easier to implement in
hardware because of the decision of the Fortran committee and not the
other way round? Not that I pretend to know how thing went exactly, but
that's a possibility. What do you think is the difference, measured in
number of transistors, between the hardware implementations of
rounding-towards-zero and rounding-towards-minus-infinity? I bet it's
negligible, so it makes perfect sense for chip-makers to follow what the
industry required, not the opposite.

Just my opinion,

Ganesh

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
 


Powered by phpBB © 2001, 2006 phpBB Group