Categories: MSDN / DotNet / Java / Scripts / Linux / PHP Ask - La ask - La Answer

Whats wrong with the C++ compiler ?

Hey;

Do u know the divison algorithm ?
It's used to give us the quotient, reminder, and make divisons ..
And it must be the one used in all compilers to solve normal division problems.

Ok in the algorithm the reminder (r) must be greater than or equal zero satisfy :
0 =< r < |n| , right ?

it's easy to make this division algorithm and to find it in too many books; now look in this code:

#include<iostream.h>
#include<windows.h>

int divison_algorithm(int m, int n)
{
//~ (c) Division algorithm ~//

//the couple <0,0> is not acceptable !
int r(m),q(0); /*[q]uotient & [r]eminder*/

/*Details===========================================
! m = qn + r , 0 =< r < |n| .
! r = m - [n + n + n ... + n] (q times)
! [m > n] or [ [m = n or m = kn] (r=0) ]
! start with q = 1 --> m = n or (m = 1*n + r)
! increse q by 1 and decrese r by 1*n (= n)
! continue until r < 3 to be a suitabel reminder.
==================================================*/

if (n<0) n = -n; //get the absolute value of n

while( r >= n || r < 0)
{
q++;
r -= n;
}

if (r<0) { //the previous while loop hasent been accede
while( -r >= n || r < 0)
{
q--;
r +=n;
}
}

//Reminder must be positive or zero value .
cout <<"q= " <<q<<endl;
return r;
}

void main(void)
{
cout<< 10%3<<endl; //ok true 10 = 3*3 + 1
cout<<divison_algorithm( 10, 3)<<endl; //ok true 10 = 3*3 + 1
cout<<-10%3<<endl; //No the reminder must be non-negative
cout<<divison_algorithm(-10, 3)<<endl; //ok true -10 = -4*3 + 2

system("PAUSE");

}

is the C++ compiler has a mistake or what's wrong ?
[2037 byte] By [Amahdy] at [2007-11-11 9:59:43]
# 1 Re: Whats wrong with the C++ compiler ?
The proof and details are here :

http://en.wikipedia.org/wiki/Division_algorithm
Amahdy at 2007-11-11 20:59:33 >
# 2 Re: Whats wrong with the C++ compiler ?
what's the error message you're getting?
Danny at 2007-11-11 21:00:40 >
# 3 Re: Whats wrong with the C++ compiler ?
I think he got a negative remainder.
jonnin at 2007-11-11 21:01:39 >
# 4 Re: Whats wrong with the C++ compiler ?
Yea jonnin is right , the reminder by definition must be positive or null .

I'm asking why c++ compiler make this or in general all compilers make this althought the algorithm is made for have a unique {q} subset from Z and a unique {r} subset from N .

I think it's more explained in the linke above .
Amahdy at 2007-11-11 21:02:44 >
# 5 Re: Whats wrong with the C++ compiler ?
Well, I wouldn't call it a compiler problem then;)
You have to debug the code and see what actually happens. Clearly, there's a bug in the program, but it's not the compiler's fault.
Danny at 2007-11-11 21:03:37 >
# 6 Re: Whats wrong with the C++ compiler ?
Anyway ignore "My listed programme" ,it was only to demonstrate the algorithme.

The originale question is about why compilers give us a negative reminder while it's not allowed , BY DEFENETION it must be positive or null .. that's what I mentioned in my code "//No the reminder must be non-negative"

Got it ? now anyone know why ? I think jonnin know what I mean but he hasn't gived us any comment .
Amahdy at 2007-11-11 21:04:48 >
# 7 Re: Whats wrong with the C++ compiler ?
I do not fully remember where, but I believe a negative remainder is handy in a few algorithms even if *mathematically* it is not desirable. I will see if I can jog my memory, but in the meantime just use abs on it or something.
jonnin at 2007-11-11 21:05:41 >
# 8 Re: Whats wrong with the C++ compiler ?
I found this blurb on one Q&A session:

There are different ways of thinking about remainders when you deal
with negative numbers, and he is probably confusing two of them. The
mod function is defined as the amount by which a number exceeds the
largest integer multiple of the divisor that is not greater than that
number. In this case, -340 lies between -360 and -300, so -360 is the
greatest multiple LESS than -340; we subtract 60 * -6 = -360 from -340
and get 20:

-420 -360 -300 -240 -180 -120 -60 0 60 120 180 240 300 360
--+--+--+--+--+--+--+--+--+--+--+--+--+--+--
| | | |
-360| |-340 300| |340
|=| |==|
20 40

Working with a positive number like 340, the multiple we subtract is
smaller in absolute value, giving us 40; but with negative numbers, we
subtract a number with a LARGER absolute value, so that the mod
function returns a positive value. This is not always what people
expect, but it is consistent.

If you want the remainder, ignoring the sign, you have to take the
absolute value before using the mod function.

- Doctor Peterson, The Math Forum
http://mathforum.org/dr.math/

But I still can't remember why I was using them at one point... who knows..
jonnin at 2007-11-11 21:06:49 >
# 9 Re: Whats wrong with the C++ compiler ?
The absolute value isn't the solution , in my example abs(-1) = 1 not equal 2 ..

Look at those few lines :
10 = 1*3 + 7 // 7 > 3 , not a remainder
10 = 2*3 + 4 // 4 > 3 , not a remainder
10 = 3*3 + 1 // 1 < 3 , the unique remainder
10 = 4*3 - 2 //-2 < 3 , also but not the remainder , why ?

Usually we need the greatest element lower than the divisor .
so -2 is lower than 3 but we have found 1 satisfy the algorithme and -2 < 1 < 3
if there is an element between 1 and 3 satisfy the algorithm we will take it but 1 is the greatest one , [we can easily show that any element lower than this greatest one will be negative (1 < 3 ==> 1 -3 < 0 ) ] it's from here where we easily say that the remainder must be positive or null (we say null not zero coz it's null if the number divide the divisor , i.e. not exist , zero exist !)

now apply this again with "-10" :
-10 = -5*3 + 5 // 5 > 3 , not a remainder
-10 = -4*3 + 2 // 2 < 3 , greatest lower than 3 , hence the unique remainder .
-10 = -3*3 - 1 // -1 < 3 , not the greatest one (negative) .

The good definition is said :
For every m,n form Z , there exist a unique q (quotient) and a unique r (remainder) form Z satisfy :
m = qn + r , in the condtion 0 =< r < n .

Now try this in cpp : -10%3 // answer is -1 which doesn't satisfy remainder conditions , or we say [2 is greater than -1 and lower than 3] or we say directly [-1 is negative !]

This usually gives us wrong answers and we want all time to return back to my sample or any similar method to correct those errors , is this an error in all compiler or ignored or what ?

P.s. : Originally I get this from someone called "Paula" (with 'a' at the end) who was asking why in cpp '%' gives us sometimes negative results which makes errors in his programming work .
Amahdy at 2007-11-11 21:07:42 >
# 10 Re: Whats wrong with the C++ compiler ?
The point was the function is modulo, not remainder, and they are defined slightly differently, if that guy was correct. This seems consistent with other posts I found when I looked it up, but none of them explained it very well.
jonnin at 2007-11-11 21:08:48 >
# 11 Re: Whats wrong with the C++ compiler ?
Same problem ! , u know the set of modulo of a number n is the numbers from 0 to n-1 ...
ig. the return of "x mod(n)" must be a number from 0 to n-1 .
example : normal Cesar Cipher text is optained by mod 26 :
30 mod 26 = 4 (D) , -3 mod 26 = -3 + 26 = 23 (W) ! [u can check this in any encryption software] .
It's commonly knowen under the equivalent class of "n" and here n must be positive which can be considered a subcase from the devision algorithm which accept negative and ZERO values also as divisors .
Amahdy at 2007-11-11 21:09:53 >
# 12 Re: Whats wrong with the C++ compiler ?
Accepting zero is the trivial method :
m = q*0 + r
Take r = m but this make some exeptions coz here r isnt less than m and q isn't unique .
Amahdy at 2007-11-11 21:10:45 >
# 13 Re: Whats wrong with the C++ compiler ?
New : it's still strange ! ..
Every body know the uniquness of solution or no solution , right ?

I went today morning to a great profeesor called : "Prof: Amer" , and asking him about this problem [he is an algorithms profeesor ] and he gived me a new answer :

as we know the original divison algorithm states :

(for all m)(for all n)(there is a unique q)(there is a unique r)[ m = qn + r , such that 0 =< r < n ]

And as we know it gives us the reminder and the quotient , the solution for them is unique then it's solvable everytime .
I can give you the prove of the "correctness" and the "uniqness" , moreover the "termination" of this algorithm .. two lemmas can show that ; if anybody want I can list them , they are small .

Now after many operations , the prof gived me the algorithm used in compilers which is :

(for all m)(for all n)(there is a unique q)(there is a unique r)[ m = qn + r , such that |r| < |n| ]

It seems at the first look the same , |r| is always non-negative , but this method accept "negative" values for "r" , before trying to prove this we can see clearly here r is not unique ! yes , in my previous example :
-10 % 3
|-1| < |3| and |2| < |3| , i.e. this algorithm gives more than one r which is not correct , if u ask about how it gives us a solution when it's not solvable ; clearly it "STOPS" after the first result and gives us wrong answer in many cases ..

I'm worried about that is it a general compiler "BUG" or what , regarding that it gives us wrong answers ! using incorrect algorithm !

Finally the professor told me it's easy to correct this in my [and Paula's] work , for now by adding n to the result , simply : <if(r<0) r += n;> but what after that , anybody discuss with me this I'm completly woried .. shall we tell compilers maker about that ?
Amahdy at 2007-11-11 21:11:52 >
# 14 Re: Whats wrong with the C++ compiler ?
My last news in this topic :
How to edit the C++ [or any language] algorithm :
As telling before the used algorithm is :

(for all m)(for all n)(there is a unique q)(there is a unique r)[ m = qn + r , such that |r| < |n| ]

And have prooved that it's wrong, now a small update to make it gives us correct answers :
we have ; 0 < |r| < |n|
if r < 0 then -|n| < r < 0
then 0 < r+|n| < |n|
let r' = r+|n|
now we have r' satisfy the original algorithm (0 < r' < |n|)
that's mean what we need exactly is to add |n| if we have an "r < 0"
~~~~~~~~~~~~~~~~~~~
Now the correction of q:
the new q is : (m - r')/n or by the simplest method : q' = (q - |n|/n) Indeed :
m = nq + r
m = nq + r + |n| - |n|
m = nq + (r + |n|) + (-|n|/n)n
m = n(q - |n|/n) + (r + |n|)
i.e. if we take r' = r + |n| then q must be changed to q' = q - |n|/n

Now the final correction to get true quotient and true reminder in C++ is :

//m , n , n>0:
q = m/n;
r = m%n;
if(r<0) { r += abs(n); q -= abs(n)/n; } //Here I'm sure about the correct results which satisfy the algo.

Please if u read this up to here just give me any comments and what's your opinion about that , compilers have wrong algorithm or i have a mistake or what .
Thank you .
Amahdy at 2007-11-11 21:12:54 >
# 15 Re: Whats wrong with the C++ compiler ?
Im fairly confused by this point. However, negative modulo results have existed for decades. If there were an error, I think someone would have noticed before now, seeing as how modulo is very commonly used. See if you can find several matching definations of modulo and compare *that* against the c++ operation, instead of against remainders, and try several compilers as well (you should always get the same result no matter what compiler). Its always possible you have discovered something that has been wrong for 25 or more years, but I just cant imagine a serious bug in so basic a routine has lasted. However, various compilers mess up logical operations on signed numbers as well, and that also surprised me, so odd things do exist in the low level implementations (Mostly by intent for whatever questionable or random reasoning).
jonnin at 2007-11-11 21:13:51 >
# 16 Re: Whats wrong with the C++ compiler ?
Thanks jonnin for reply;

However, negative modulo results have existed for decades.

If we can accept the negative modulo we finally need the positive one , as I told u before if I got a negative in encryption for example I'll not have any sence about what the negative number point to .

If there were an error, I think someone would have noticed before now, seeing as how modulo is very commonly used.

I agree with u it seems there isn't error but what's wrong with "ME" ? , after my small experience I can see that majority of encryption programmers prefere their owen method of modulo in their application , maybe this is because they know the error and ignore it, or because of this they haven't seen the error before !

See if you can find several matching definations of modulo and compare *that* against the c++ operation, instead of against remainders,

I don't agree with u about finding several definition for "Standard" operation in math specially , and the correct defenition as I told u before : mod(n) are the equivalent class from 0 to n-1 ; yes I know the equivalent class contains negative numbers in them but why we use mod from begining ... if I have (n+5) I use mod n to get 5 and if I have (-3) I use mod n to get n-3 , and so on .. so results must be from 0 to n-1 .

and try several compilers as well (you should always get the same result no matter what compiler).

I already know , all languages have same problem .

Its always possible you have discovered something that has been wrong for 25 or more years, but I just cant imagine a serious bug in so basic a routine has lasted.

I didn't , it's "Paula" 's :) .. I got confused from this so I'm asking here !

ok thank u anyway I'll look again throw this all maybe I can find something .
Amahdy at 2007-11-11 21:14:56 >
# 17 Re: Whats wrong with the C++ compiler ?
You write your own mod for encryption because the standard one cannot handle the large integers used in encryption, right?
jonnin at 2007-11-11 21:15:59 >
# 18 Re: Whats wrong with the C++ compiler ?
One of its uses ,,
Amahdy at 2007-11-11 21:16:52 >
# 19 Re: Whats wrong with the C++ compiler ?
thanks for Amady...
first i want to post my thanks and hope to solve that problem but...
why the compiler give us that result??
Is who made the compilers wasn't know the division algorithm and dosen't know that must gives a uniqe (q) and a uniqe(r) ??!!!!!!
i.e. they know or not that :
for all m in Z and n in Z-{0} There exist unique integers q and r such that a = qd + r and 0 ≤ r < | d |, where | d | denotes the absolute value of d.

If the answer was yes, they were know.
why they did that bug (as I see and sure you with me) ..are they couldn't !!! sure no..
and so the question become why they did that ??

If the answer was No, they weren't know.
now we know that this is a bug ... moreover they weren't know that !!
the question become what we can do to solve that bug?

I as a normal user can't think that the computer give me a rong result ...
and that's our problem and we must solve it But HOW ??
Paula at 2007-11-11 21:17:58 >
# 20 Re: Whats wrong with the C++ compiler ?
sorry for that default
Paula at 2007-11-11 21:18:54 >
# 21 Re: Whats wrong with the C++ compiler ?
Ohhhhhhhhh :mad: :mad: , relly sorry for that defaul
for all m in Z and n in Z-{0} There exist unique integers q and r such that a = qd + r and 0 ≤ r < | d |, where | d | denotes the absolute value of d.

the correct is :
for all m in Z and n in Z-{0} There exist unique integers q and r such that m = qn+ r and 0 ≤ r < | n |, where | n | denotes the absolute value of d.
Paula at 2007-11-11 21:20:00 >
# 22 Re: Whats wrong with the C++ compiler ?
Hey Paula, it's a great honor to see u with us here :WAVE:
Next time make a suitable switch case :
switch(answer)
{
case yes: they know ...
case no : they don't know ...
}
:D

I only want u remember that , of corse they know but the problem why those great computer scientists made compilers on this form ? here we can make the new switch case:
-there is a reason for that --> what is it ?
-there isn't a reason --> how to report that bug for all compilers scientists to repair it ? .. I'm series in cryptologie for example it gives us wrong answers ! it's not the true remainder that we expect in our work !

Thanks again Paula for your reply , hope that anybody can give us what's wrong with us or wrong with more than 25 years used language !
Amahdy at 2007-11-11 21:20:54 >
# 23 Re: Whats wrong with the C++ compiler ?
Hi,

While mathematically correct, your assumptions fail to notice two points:

it is not the compiler that performs the calculations, but the microprocessor. The compiler just translates the code into suitable machine instructions, in this case the instruction that performs the calculation is IDIV, so, -10 % 3 translates into something in the lines of:

mov eax, -10 ; load dividend value
mov ebx, 3 ; load divisor
idiv ebx ; perform integer signed division
; now eax contains the quotient (-3 in this case)
; edx contains the remainder (-1 in this case)So, don't blame your compiler (nor the "great computer scientists" that made that compiler), at least not for this specific "bug".

Intel, in its Software Developer Manual, clearly states how IDIV works and explicitly indicates that:

non-integral results are ALWAYS truncated (chopped) towards 0. Which means IDIV will divide until the absolute value of the reminder is lower than the absolute value of the divisor and no further (which is, in substance, what you ask for, in order to obtain a positive remainder).
the sign of the reminder is ALWAYS the same as the sign of the dividend (in this case, -1 has the same sign as -10).

Is it a bug? Well, It could be said that mathematically speaking the result is not "what was expected" (at least by you). But certainly it is not incorrect, either (the result does satisfy Dividend = Divisor * Quotient + Reminder).

This has to do with the way division is implemented in the processor's ALU (Arithmetic Logic Unit), and the divider circuit's limitations. You can get an idea of the algorithms used for division in circuits by taking a look here (en.wikipedia.org/wiki/Division_%28electronics%29).

IMHO, programming requires one to acknowledge these constraints and, where necessary, devise a way around the limitations the architecture pushes on you. After all, most cyphering programs work correctly, despite this detail...
mikkus at 2007-11-11 21:22:00 >
# 24 Re: Whats wrong with the C++ compiler ?
First thank u very much mikkus for this great post ;

Now, after looking again I found that u r right about my mistake in saying "compiler" problem , I didn't know before that there is an "idiv" only "div" and I thinked that the compiler generate a simple loop doing that . actually this solve more than the half of the problem ; because in this case as u said it's not a problem for all compilers scientists , only a processor issue, or specially Intel architecture [I don't know what sun and mac do] ..

-about the manual , I have only pentium 1 manual so please tell me where is it exactly , It's only to read the complete article I'm interisted in this .

"the sign of the reminder is ALWAYS the same as the sign of the dividend "
this where I want to stop coz as explained in my earlier posts it's not what we expect , bref: it's not the correct answer that we want .

"programming requires one to acknowledge these constraints "
I'm sorry but I think u exagere here , not all programmers must know all things ,it's usually good to know lot of things about this but not be an assembler and it's not very nessesary .

"After all, most cyphering programs work correctly, "
maybe u haven't read all the topic , I mentioned that and I said that they use their owen function to make the mod function , and I have provided solutions for the main algorithm so why we must respect the "limitations the architecture pushes on you" , why not report to the architecturers to repair it ,, this what I mentioned too u think that it'm my problem only and I confirm it's a problem in cryptologie but I think programmers ignore it [or so what?] .

"the result does satisfy ..." we don't want satisfying only, we need the uniquness ,

a + b = 2 , a could be 1 and b = 1 but maybe I [the sender] mean a = 0 and b = 2
so as I said before this digital algorithm can be simply solved I think using my provided solutions made by my great prof : dr-Amer .

Thank u again for your great reply.
Amahdy at 2007-11-11 21:23:00 >
# 25 Re: Whats wrong with the C++ compiler ?
Hi, Amahdy,

First off, the manual I'm referring to is located here (http://www.intel.com/design/processor/manuals/253666.pdf). This is the first part of the instruction set, volume 2A. Just search for the IDIV instruction in the index. The rest of the volumes can be downloaded here (http://www.intel.com/products/processor/manuals/index.htm) along with some optimization guides. You can find similar info in AMD's website, for their respective processors.

With regards to the fact that this is a bug, I'll just refer to Wikipedia (entire article here (http://en.wikipedia.org/wiki/Remainder)) which states:

The way remainder was defined, in addition to the equality a=qd+r an inequality was also imposed, which was either 0≤ r < |d| or -|d| < r ≤ 0. Such an inequality is necessary in order for the remainder to be unique that is, for it to be well-defined. The choice of such an inequality is somewhat arbitrary. Any condition of the form x < r ≤ x+|d| (or x ≤ r < x+|d|), where x is a constant, is enough to guarantee the uniqueness of the remainder.

With two choices for the inequality, there are two possible choices for the remainder, one is negative and the other is positive. This means that there are also two possible choices for the quotient. Usually, in number theory, we always choose the positive remainder. But programming languages do not. C99 and Pascal choose the remainder with the same sign as a. (Before C99, the C language allowed either choice.) Perl and Python choose the remainder with the same sign as d.

In the excerpt, a is the dividend, d is the divisor, q is the quotient and r is the remainder. As you see, there have been different ways of approaching this and neither is inherently wrong.

Of course, when I said programmers had to know these details I was just generalizing, saying that a programmer should be prepared to circumvent a problem when it comes up, instead of "blaming it to the hardware". After all, hardware is known to have limits.
mikkus at 2007-11-11 21:24:00 >
# 26 Re: Whats wrong with the C++ compiler ?
How can I miss that ! I'm was talking about my hardcopy and I have missed that it must be somewhere on the internet an eCopy , thank u for the link !
**I haven't found exactly what u mentioned but generally the idiv results table explain it .

look the operation "or" make more than one answer, if each answer is true then the or make one or both of them true , as u said they expect in math the positive one and in programming depends [they mustn't say programming lang. but proccessor arch. ] however as every body know that (math implies computer) without math we couldn't make any updates in computer science , usualy we make theorems and we apply it in computer using many algorithms ,, like divison theorem , and like any encryption algorithm .
Okey tell me where we need this remainder ? and in my post number 15 here after the small if condition , can't we repair this digitally or programatically to have the normal needed remainder ? I think it's easy digitally , and this hardware limit could be corrected to solve what we all usually need .
Amahdy at 2007-11-11 21:25:07 >
# 27 Re: Whats wrong with the C++ compiler ?
You posted a solution for the problem already, checking if the reminder is negative and adjusting the results seems to be the correct, and only, way to go.

This could come as news to you, but actually computers are terrible mathematicians... they are too limited in the way they represent numbers, to begin with. In computers, most advanced (and not so advanced) math is either simulated or approximated. For example, a computer does not natively understand negative numbers, or real numbers, it just simulates them, but at the cost of precision.
mikkus at 2007-11-11 21:26:07 >
# 28 Re: Whats wrong with the C++ compiler ?
"This could come as news to you, but actually computers are terrible mathematicians" :o

I don't know why u r talking about this limit as if it's huge problem .. I mentioned before too the used algorithm and the solution .. I haven't read too much in the computer phisics but finally to implimint the "idiv" for example they make a similar to a loop and it stops at the first number which is sometimes negative .. this loop couldn't be ameliored , or such an if condition couldn't be implimented with this bid processor technologie ?
otherwise in the article they mentioned :
"... But programming languages do not. C99 and Pascal choose the remainder with the same sign as a ..." are they true by saying programming langs ?

And u tell me some computer architecture basis , I'm not expert or a big savant but do u think if I'm talking about this topic I don't know that "a computer does not natively understand negative numbers" or "they are too limited in the way they represent numbers" ?

Thanks very much mikkus for your great replies and I hope really find a final response in this topic or I'm wrong in somewhere or we should tell *** to upgrate this .
Thank u.
Amahdy at 2007-11-11 21:27:08 >