473,395 Members | 1,891 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

What does % really do?

This is from ISO/IEC 14882:2003(E) §5.6 ¶4
<quote>
The binary / operator yields the quotient, and the binary % operator yields the remainder from the division
of the first expression by the second. If the second operand of / or % is zero the behavior is undefined; oth-
erwise (a/b)*b + a%b is equal to a. If both operands are nonnegative then the remainder is nonnega-
tive; if not, the sign of the remainder is implementation-defined).
</quote>

How precisely does that actually define the behavior of these operators? I haven't given this last point a
great deal of thought yet, but I believe you could define division of a negative integer by a positive integer
in such a way as to always have a positive remainder. That is, the quotient would be the integer with a magnitude one
greater than the previous whole number division, e.g. -24/5 = -5, with the remainder of 1. That gives
a=-24, b=5, a/b=-5, a%b=1, (a/b)b=-25, (a/b)*b + a%b=-24.

Here's something interesting to consider. I started looking at the way C++ handles the % operator, and found that the
the behavior of my compiler is different from that of Mathematica in this respect. I also looked at K&R where I saw
that they were rather explicit about not defining which choice from the above options could be used. Look at the
output of the C++ program compared with the Mathematica version of (almost) the same program. I will note that the
C++ Standard does not call the % operation 'modulo', at least not in the above quoted paragraph. The is, however, often
called that. I contend that the behavior of my C++ compiler does _not_ provide a true modulo operation. A true molulo
operator would produce only one modulus per equivalence set. The program below does not do that.

#include <iostream>
#include <vector>
#include <map>
#include <iomanip>

typedef std::vector<int> intVector;
typedef std::map<int,intVector> equivalenceSets;

void printEquivelenceSets(equivalenceSets& es, int n) {

for(equivalenceSets::iterator it = es.begin(); it != es.end(); ++it ) {

std::cout<<"modulus = "<<std::setw(2)<<it->first<<" "<<"{";

for(unsigned j = 0; j < it->second.size(); ++j) {
if(j) std::cout << ", ";
std::cout<<std::setw(4)<< it->second[j];
}
std::cout<<"}"<<std::endl;
}

std::cout<<std::endl;
for(equivalenceSets::iterator it = es.begin(); it != es.end(); ++it ) {

std::cout<<"modulus = "<<it->first<<" "<<"{";

for(unsigned j = 0; j < it->second.size(); ++j) {
if(j) std::cout << ",";
if(!(it->first || it->second[j])) std::cout << std::endl;

std::cout<<"("<<it->second[j]<<"-";

if(it->first < 0) std::cout<<"("<<it->first<<")";
else std::cout<<it->first;

std::cout<<")/"<<"("<<n<<")="<<float(it->second[j] - it->first)/float(n);
}
std::cout<<"}"<<std::endl;
}
}

int main() {
int a(0);
int b(0);
int n(5);

equivalenceSets es;

for (int a = -25; a < 26; ++a ) {
es[a%n].push_back(a);
}

printEquivelenceSets(es, n);
}
modulus = -4 { -24, -19, -14, -9, -4}
modulus = -3 { -23, -18, -13, -8, -3}
modulus = -2 { -22, -17, -12, -7, -2}
modulus = -1 { -21, -16, -11, -6, -1}
modulus = 0 { -25, -20, -15, -10, -5, 0, 5, 10, 15, 20, 25}
modulus = 1 { 1, 6, 11, 16, 21}
modulus = 2 { 2, 7, 12, 17, 22}
modulus = 3 { 3, 8, 13, 18, 23}
modulus = 4 { 4, 9, 14, 19, 24}

modulus = -4 {(-24-(-4))/(5)=-4,(-19-(-4))/(5)=-3,(-14-(-4))/(5)=-2,(-9-(-4))/(5)=-1,(-4-(-4))/(5)=0}
modulus = -3 {(-23-(-3))/(5)=-4,(-18-(-3))/(5)=-3,(-13-(-3))/(5)=-2,(-8-(-3))/(5)=-1,(-3-(-3))/(5)=0}
modulus = -2 {(-22-(-2))/(5)=-4,(-17-(-2))/(5)=-3,(-12-(-2))/(5)=-2,(-7-(-2))/(5)=-1,(-2-(-2))/(5)=0}
modulus = -1 {(-21-(-1))/(5)=-4,(-16-(-1))/(5)=-3,(-11-(-1))/(5)=-2,(-6-(-1))/(5)=-1,(-1-(-1))/(5)=0}
modulus = 0 {(-25-0)/(5)=-5,(-20-0)/(5)=-4,(-15-0)/(5)=-3,(-10-0)/(5)=-2,(-5-0)/(5)=-1,
(0-0)/(5)=0,(5-0)/(5)=1,(10-0)/(5)=2,(15-0)/(5)=3,(20-0)/(5)=4,(25-0)/(5)=5}
modulus = 1 {(1-1)/(5)=0,(6-1)/(5)=1,(11-1)/(5)=2,(16-1)/(5)=3,(21-1)/(5)=4}
modulus = 2 {(2-2)/(5)=0,(7-2)/(5)=1,(12-2)/(5)=2,(17-2)/(5)=3,(22-2)/(5)=4}
modulus = 3 {(3-3)/(5)=0,(8-3)/(5)=1,(13-3)/(5)=2,(18-3)/(5)=3,(23-3)/(5)=4}
modulus = 4 {(4-4)/(5)=0,(9-4)/(5)=1,(14-4)/(5)=2,(19-4)/(5)=3,(24-4)/(5)=4}
(*Mathematica version of the same program*)

getIndex[r_Integer, eqsl_List] := 0 /; eqsl === {} || Position[eqsl, {r, ___}] === {}
getIndex[r_Integer, eqsl_List] := Position[eqsl, {r, ___}][[1, 1]]

addToEqSetList[r_Integer, n_Integer, eqsl_List] := {{Mod[r, n], r}} /; eqsl === {}

addToEqSetList[r_Integer, n_Integer, eqsl_List] :=
Module[{i = getIndex[Mod[r, n], eqsl]},
ReplacePart[eqsl, Append[eqsl[[ i ]], r], i] /; i > 0]

addToEqSetList[r_Integer, n_Integer, eqsl_List] := Append[eqsl, {Mod[r, n], r}]

eqSetList = {};
n = 5;
r = 25;
Do[eqSetList = addToEqSetList[i, n, eqSetList], {i, -r, r}]

eqSetList // TableForm

0 -25 -20 -15 -10 -5 0 5 10 15 20 25

1 -24 -19 -14 -9 -4 1 6 11 16 21

2 -23 -18 -13 -8 -3 2 7 12 17 22

3 -22 -17 -12 -7 -2 3 8 13 18 23

4 -21 -16 -11 -6 -1 4 9 14 19 24

--
If our hypothesis is about anything and not about some one or more particular things, then our deductions constitute mathematics. Thus mathematics may be defined as the subject in which we never know what we are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #1
8 5271
Steven T. Hatton wrote:

Replace equivalence set, with equivalence class. I'm tired.

--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #2
"Steven T. Hatton" <ch********@germania.sup> wrote in message
news:4c********************@speakeasy.net...
This is from ISO/IEC 14882:2003(E) §5.6 ¶4
<quote>
The binary / operator yields the quotient, and the binary % operator
yields the remainder from the division
of the first expression by the second. If the second operand of / or % is
zero the behavior is undefined; oth-
erwise (a/b)*b + a%b is equal to a. If both operands are nonnegative then
the remainder is nonnega-
tive; if not, the sign of the remainder is implementation-defined).
</quote>

How precisely does that actually define the behavior of these operators? I
haven't given this last point a
great deal of thought yet, but I believe you could define division of a
negative integer by a positive integer
in such a way as to always have a positive remainder.


Yes. It just happens that on some processor architectures,
the 'modulo' operation with negative operands does not always
provide a positive result. In the same fashion, (-3)/2 may
yield -1 or -2, depending on the processor.

And to avoid forcing implementations to add special handling
for this 'unusual' case of non-positive integer division, it
had been decided to leave this choice up to the implementation.

Obviously, Mathematica, Java, C#, and other language/platform
specifications have made a different choice. And nowadays,
this freedom of implementation seems archaic (and some have
suggested to remove it), but that's the way C and C++ are...
hth -Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <> http://www.brainbench.com
Jul 23 '05 #3
Ivan Vecerina wrote:

Obviously, Mathematica, Java, C#, and other language/platform
specifications have made a different choice. And nowadays,
this freedom of implementation seems archaic (and some have
suggested to remove it), but that's the way C and C++ are...


They're that way because it's fast. If you want slow and always positive
you can write it. If the language requires slow and always positive you
can't make it fast.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 23 '05 #4
"Pete Becker" <pe********@acm.org> wrote in message
news:Ao********************@giganews.com...
Ivan Vecerina wrote:

Obviously, Mathematica, Java, C#, and other language/platform
specifications have made a different choice. And nowadays,
this freedom of implementation seems archaic (and some have
suggested to remove it), but that's the way C and C++ are...


They're that way because it's fast. If you want slow and always positive
you can write it. If the language requires slow and always positive you
can't make it fast.


Well, you could have it be fast with unsigned operands anyway.
And for signed operands, how useful is an unpredictable result?

This said, things are the way they are, and I'm fine with it.
And I'm not up for a debate which must have been hashed out already...

Regards,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <> http://www.brainbench.com
Jul 23 '05 #5
Ivan Vecerina wrote:

Well, you could have it be fast with unsigned operands anyway.
It _is_ fast for unsigned operands.
And for signed operands, how useful is an unpredictable result?
It's not unpredictable. It's implementation-defined, within the
constraints imposed by its definition, which means it is one of two
possible values. If you want a non-negative remainder, just check it. If
it's negative, add the absolute value of the denominator.

This said, things are the way they are, and I'm fine with it.
And I'm not up for a debate which must have been hashed out already...


Then don't make provocative (and erroneous) statements.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 23 '05 #6
"Pete Becker" <pe********@acm.org> wrote in message
news:A5********************@giganews.com...
Ivan Vecerina wrote:

Well, you could have it be fast with unsigned operands anyway.


It _is_ fast for unsigned operands.


Yes, my point was that it *could* still be fast for unsigned operands,
had the specification strictly defined the result of a signed operation.
And for signed operands, how useful is an unpredictable result?


It's not unpredictable. It's implementation-defined, within the
constraints imposed by its definition, which means it is one of two
possible values. If you want a non-negative remainder, just check it. If
it's negative, add the absolute value of the denominator.


I obviously understand this. Why are you nitpicking on wording?
From the perspective of a C++ programmer writing portable code,
it is not strictly predictable - since a run-time test and
fix is likely to be required.

Now since you are keeping this discussion going:
Could you provide us with real-life examples were the remainder of
a signed division is needed, but the sign of the result is indifferent?

I could not think of such a case.
But I guess the point is to support fast division with signed operands,
and I understand that the rounding in this case may have to be
implementation-defined, for performance reasons. And it is obviously
essential to keep the results of % and / consistent.

Other standards committees have chosen a different approach. As I said,
I'm fine with either choice - you don't need to preach and convert me.
I just tried to explain the situation to the OP, and I did my best
to expose it in a neutral light. ( forgive me, I'm Swiss ;) )
This said, things are the way they are, and I'm fine with it.
And I'm not up for a debate which must have been hashed out already...


Then don't make provocative (and erroneous) statements.


The provocativeness of my previous 4-line post has totally escaped me
- I would be thankful if you could explain what was so sensitive in it.
I do not see either how my comment was fundamentally erroneous - in
what way could it have misled or otherwise harmed the OP ?
Kind regards,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Jul 23 '05 #7
Ivan Vecerina wrote:
"Pete Becker" <pe********@acm.org> wrote in message
news:A5********************@giganews.com...
Ivan Vecerina wrote:
Well, you could have it be fast with unsigned operands anyway.
It _is_ fast for unsigned operands.

Yes, my point was that it *could* still be fast for unsigned operands,
had the specification strictly defined the result of a signed operation.


Oh, so your point was that making signed divisions slow would be okay
because it wouldn't affect unsigned divisions. Okay, true, but not
particularly relevant. The basic principle of C and C++ is that you
don't pay for what you don't use.
And for signed operands, how useful is an unpredictable result?


It's not unpredictable. It's implementation-defined, within the
constraints imposed by its definition, which means it is one of two
possible values. If you want a non-negative remainder, just check it. If
it's negative, add the absolute value of the denominator.

I obviously understand this. Why are you nitpicking on wording?
From the perspective of a C++ programmer writing portable code,
it is not strictly predictable - since a run-time test and
fix is likely to be required.


"Unpredictable" is not a word I would use to describe something that's
perfectly well defined, clear, and easily manageable.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 23 '05 #8
"Ivan Vecerina" <IN*************************@vecerina.com> wrote in message
news:d8**********@news.hispeed.ch...
I could not think of such a case.
But I guess the point is to support fast division with signed operands,
and I understand that the rounding in this case may have to be
implementation-defined, for performance reasons. And it is obviously
essential to keep the results of % and / consistent.


The real issue is much simpler: The C++ committee decided early in the game
to maintain compatibility with C in fundamental areas such as arithmetic.
C89, on which C++ is based, defines % and / so as to allow the
implementation's hardware arithmetic to show through, so C++does the same.

I believe that C99 requires that the result of % have the same sign as the
dividend. If my belief is correct, I am confident that C++ will follow suit
in its next revision.
Jul 23 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

92
by: Reed L. O'Brien | last post by:
I see rotor was removed for 2.4 and the docs say use an AES module provided separately... Is there a standard module that works alike or an AES module that works alike but with better encryption?...
125
by: Sarah Tanembaum | last post by:
Beside its an opensource and supported by community, what's the fundamental differences between PostgreSQL and those high-price commercial database (and some are bloated such as Oracle) from...
7
by: steve bull | last post by:
I have the following code snippet to read the colorRange attributes for the colorRangeSwatch in the xml file listed below. string expr = "/swatches/colorRangeSwatch/colorRange";...
44
by: lester | last post by:
a pre-beginner's question: what is the pros and cons of .net, compared to ++ I am wondering what can I get if I continue to learn C# after I have learned C --> C++ --> C# ?? I think there...
35
by: GTO | last post by:
I do not believe that C# is the future of C++. I also do not believe that adding two thousand new library functions to the standard library is the future of C++. But what is the future of C++? Is...
121
by: typingcat | last post by:
First of all, I'm an Asian and I need to input Japanese, Korean and so on. I've tried many PHP IDEs today, but almost non of them supported Unicode (UTF-8) file. I've found that the only Unicode...
24
by: Bob Alston | last post by:
Most of my Access database implementations have been fairly small in terms of data volume and number of concurrent users. So far I haven't had performance issues to worry about. <knock on wood> ...
21
by: Helge Jensen | last post by:
I've got some data that has Set structure, that is membership, insert and delete is fast (O(1), hashing). I can't find a System.Collections interface that matches the operations naturally offered...
13
by: Jason Huang | last post by:
Hi, Would someone explain the following coding more detail for me? What's the ( ) for? CurrentText = (TextBox)e.Item.Cells.Controls; Thanks. Jason
669
by: Xah Lee | last post by:
in March, i posted a essay “What is Expressiveness in a Computer Language”, archived at: http://xahlee.org/perl-python/what_is_expresiveness.html I was informed then that there is a academic...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.