This article is within the scope of WikiProject Computing, a collaborative effort to improve the coverage of computers, computing, and information technology on Wikipedia. If you would like to participate, please visit the project page, where you can join the discussion and see a list of open tasks.ComputingWikipedia:WikiProject ComputingTemplate:WikiProject ComputingComputing articles
This article is within the scope of WikiProject Mathematics, a collaborative effort to improve the coverage of mathematics on Wikipedia. If you would like to participate, please visit the project page, where you can join the discussion and see a list of open tasks.MathematicsWikipedia:WikiProject MathematicsTemplate:WikiProject Mathematicsmathematics articles
Rename section "Computing a multiplicative inverse in a finite field" as "Computing modular inverse" and include in it inverse modulo an integer and inverse in an algebraic field extension, including inverse in a finite field of non-prime order. D.Lazard (talk) 23:30, 3 November 2013 (UTC)
I cleaned up the pseudocode by simply replacing it with a functioning C program, instead. This should make things a lot more clear, plus anyone can easily compile it and run it themselves. If you see any problems with the program, email me at alex.woody@gmail.com. Thanks!
hello. Don't you think it is confusing to have this gcd/hcf thing all along the text?
I believe that if this hcf thing is really important at all, this alternative name should stick to that phrase in the first sentence.
If someone here really belives that HCF is the best name to call the gcd, then perhaps we can change the whole text to hcf, and keep gcd only in the first sentence. It's extremelly awkward to me, but it's better than having the operation called by two names all the time, don't you think?...
Every mathematical text have this problem with what nomenclature to adopt. This is to be defined on a prologue, and the rest of the text should use a unique notation and nomenclature. Bringing the problem to the body of the text is extremmlly confuse.
Also for the pseudocode below, it would be nice to mention that "<>" means not equals to. Does any programming language use that syntax. Is it a standard syntax used in psuedocode?
Notice that the first method in article is iterative rather than recusive in nature: it employs the quotient in the same order they appear/ the algorithm proceed forward. Compare this with the second method described, which is really a recursion and notice how they use the quotient in the reverse order they appear/ it work backward. Thus it is reasonable that the pseudocode is so long and seemingly complicated in the first method: it uses recursion rather than iteration. I suggest the code and the function call can be rewritten in an iterative fashion. Thanks. --Lemontea14:47, 26 January 2006 (UTC)[reply]
I've refactored quite some sections of this article, here are something I would like to see get handled:
Cleanup the informal description part I've written. Proofread it, check its tone, etc.
Help format the table and layout of this article in general.(e.g. the last table in the iterative method section could do some highlighting, just as the last table do)
Gives commments on the style of the informal formulation section: is it suitable to intermix the example with the theory(that is, explain the theory, then demostrate it in action, then some theory again, and so on), or is it good to completely separate them? Partly because of the messy nature of this algorithm, and partly because of easy understanding and readibility(could have drowned off if it were pure theory), I've chosen the first one.
Does The formal description part need a description of finding out x and y: just like those written out by bulleted list(see other algorithm page for examples), or does the pseudocode suffice?
I removed a link to an .exe file (presumably a Windows executable, compiled from one of the source code examples). Since there are other, safer, demonstrations, I think it's worth it to minimise the risk of Wikipedia being used to spread malicious software.
In case someone strongly disagrees, I left the original link commented out in the references section.
There is a representation of the EEA step -- that thing -- as a matrix multiplication. Mine source is Gregory & Krishnamurthy, "Methods and Applications of Error-Free Computation", Springer, 1984. The respresentation itself is
I've remmoved the link to the C++ source code program as it seems like a broken one :
azi@magicb0x ~ $ g++ mulinv.cpp
mulinv.cpp:3:16: error: ronh: No such file or directory
mulinv.cpp: In function 'int main()':
mulinv.cpp:50: warning: converting to 'int' from 'double'
mulinv.cpp:53: error: 'mod' was not declared in this scope
mulinv.cpp:72: error: 'mod' was not declared in this scope
mulinv.cpp:89: error: 'mod' was not declared in this scope
azi@magicb0x ~ $
One should explain the table method more accurately. The method described does not return the values shown in the table, neither for using always 5 nor for using the divider...
I'm not sure how to fix it (if it can be done), but the numbered steps at the end of this section overlap the table in every browser I have. This is mostly a suggestion, but it might make the page (slightly) easier to read.
I have cleaned up the iterative method section and used equations to express what was previously written only as text. I hope this new version is much clearer. Cintrom (talk) 18:42, 21 January 2008 (UTC)[reply]
"In this case, the remainder in the last but one line (which is 1) indicates that the gcd is 1; that is, 120 and 23 are coprime (also called relatively prime)." As a reader, I'm completely unable to parse what the heck "in the last but one line (which is 1)" is supposed to mean. What is a in-the-last-but-one-line? —Preceding unsigned comment added by 146.113.43.88 (talk) 20:43, 7 February 2008 (UTC)[reply]
There are five lines. The last line is the fifth line. The last-but-one line is the fourth line. This might be clearer with hyphens. Algebraist13:01, 8 March 2008 (UTC)[reply]
I'd suggest the recursive version should return the gcd. Then the proof of correctness doesn't have to link off to another article. The code to return the triple becomes something like:
euc' a 0 = (1, 0, a)
euc' a b = (k,j-k*(div a b), g)
where (j, k, g) = euc' b (mod a b)
We could (but probably shouldn't) include a pretty print:
euc a b = (show n) ++ "*" ++ (show a) ++ " + " ++ (show m) ++ "*" ++ (show b) ++ " = " ++ (show g)
where (n,m,g) = euc' a b
When using negative input in the algorithms of this page might produce a negative gcd. However the article on the Greatest common divisor states, that it "is the largest positive integer that divides both numbers without remainder". The problem is trivial to fix (if the result is negative, just multiply everything by -1), but I am unsure where on the page this should be noted.
NB:The Euclidean algorithm page has the same problem. --caramdir (talk) 19:23, 3 March 2009 (UTC)[reply]
I agree with your point. But I want to make a bit more complicated. As the number field gets more advanced which gcd you want isn't always clear. For example
Its of course true the in general does not speak about the gcd, but a. (Btw, the ring in your example should probably be .) However the Greatest common divisor and Euclidean algorithm articles almost exclusively speak about the gcd in the integers. Here the convention makes sense because otherwise you would have to replace all the "=" signs. It's probably best to include the info the the gcd is not unique in all three articles. caramdir (talk) 18:43, 16 March 2009 (UTC)[reply]
Actually allowing negative values and also allowing negative results can be important to easily balance the GCD function with the EXTENDED function. Since the results need to match, i.e.:
My revert of User:Luckyblue1's deletion of the C implementation was itself reverted by Special:Contributions/130.86.206.33. All of the edits were without explanation, and so I was perhaps rather quick to assume vandalism, but then I didn't give an explanation myself either so maybe the latter one assumed I was the vandal here. I am just an occasional editor myself, so to avoid an edit war I am hereby asking here: Should the C implementation stay or not? --Ørjan (talk) 00:53, 21 November 2009 (UTC)[reply]
My answer to this is that the C implementation should remain cut. The existing pseudo-code is sufficient to develop a C implementation quickly and the mathematics can be easily followed and related to the mathematic algorithms developed elsewhere on the page. By contrast, the C implementation was opaque and provided little clarification. Inclusion of the C algorithm changes the page's purpose from providing explanation to providing an _efficient_ algorithm targeted at a particular language. Along these lines, we might include specific efficient algorithms for all languages, which is somewhat absurd.
--Finog (talk) 16:59, 5 December 2009 (UTC)[reply]
The only reason I had the C implementation there in the first place was because the existing pseudocode at the time was horrible and inaccurate. If the C code compelled someone to write between pseudocode, then my job is done. My only fear is that the reason that code was taken down was because someone used it for something that they didn't want to get traced back to this page.
Shouldn't this article state Euclids name and where he described this algorithm, somewhere? Or, if he did not come up with the extension then, shouldn't it state who did?
80.126.179.57 (talk) 13:03, 27 April 2010 (UTC)[reply]
Hey! Where did k come from? it's not in the table!
"To find the third row of the table in the example, just notice that 120 divided by 23 goes 5 times plus a remainder. This gives us k, the multiplying factor for this row."
The sentence quoted is another way of saying "Let "; but that may still be a bit obscure. The point is that you divide by, call the integer quotient , and call the remainder . —Tamfang (talk) 04:08, 27 January 2011 (UTC)[reply]
The so-called "Proof of correctness" is woefully lacking. It makes claims like, "we know that..." without first establishing or in any way justifying the conclusion. It then proceeds with steps which do not appear to follow from that bit which, "we know." This cannot be called a proof at all, and I suggest it be removed until something vaguely proof-like can be substituted. --Prestidigitator (talk) 06:48, 6 March 2011 (UTC)[reply]
I've redone the proof as a proper inductive argument, in the mean time proving termination, cleaning up the algorithm itself so that it avoids dividing abyb twice in (almost) every call, and proving ax + by is nonnegative. Hope this helps. Marc van Leeuwen (talk) 11:38, 6 March 2011 (UTC)[reply]
The "external link" "How to use the algorithm by hand" is broken. I don't recall what to do in that case, if s/o knows, please do it. — MFH:Talk20:08, 7 August 2011 (UTC)[reply]
for a=79 and b=166 codes return -21 and 10. But it should be 145 and -69. The proof: 79*(-21) MOD 166 gives -165 (wrong! it should be 1), but 79 * 145 MOD 166 gives right 1.--The foe (talk) 23:45, 29 July 2012 (UTC)[reply]
No, that's not an error. The problem is that you are using a MOD which gives a negative result when just the first argument is negative. And your correction doesn't help; you just get a similar problem with 166*(-69) MOD 79 == -78 instead.
However it's mathematically more logical to use a MOD which always gives a nonnegative result when the second argument is positive; then you always have (x MOD z) == (y MOD z) precisely when x ≡ y (mod z). In the congruence view there is no real difference, as -165 ≡ 1 (mod 166).
Programming languages differ widely in how modulo behaves with negative numbers, see Modulo_operation#Remainder_calculation_for_the_modulo_operation. The C language even leaves it up to the implementation, to allow whichever is most efficient. As I recall, it turns out that e.g. on x86 CPUs the version which gives negative numbers is a single machine code instruction, which means that it is the one C compilers are almost certain to use. On the other hand, the more mathematically minded Haskell language provides both versions as rem and mod, with rem the x86 version and mod the more mathematical one. --Ørjan (talk) 20:01, 30 July 2012 (UTC)[reply]
Answer : by Euclid's algorithm and the lobbying method (your iterative method)
276 - 232•1 = 44; 232 - 44•5 = 12; 44 - 12•3 = 8; 12 - 8•1 = 4; 8 - 4•2 = 0. We claim that GCD (232, 276) = 4!!! and prove this by
(i) Walking through the five identities from right to left: 4 is a common divisor 0 and 4; 4 is a common divisor of 4 and 8; 4 is a common divisor of 8 and 12; 4 is a common divisor of 12 and 44; 4 is a common divisor of 44 and 232; 4 a common divisor of 232 and 276.
(ii) Walking through the identities from left to right : let d be a common divisor of 276 and 232; d a common divisor of 232 and 44; d a common divisor of 44 and 12; d a common divisor of 12 and 8; d a common divisor of 8 and 4. Xoagus (talk) 20:10, 24 June 2013 (UTC)[reply]
Note , by completing these two itineraries one sees : 4 is a common divisor of 232 and 276 and each common divisor of 232 and 276 is a divisor of 4. This means 4 is the greatest common divisor of 232 and 276. — Preceding unsigned comment added by Xoagus (talk • contribs) 20:26, 24 June 2013 (UTC)[reply]
(iii) One more walk from right to left : 4 = 12 - 8•1 = 12 - [44 - 12•3] •1 = 12•4 - 44•1 = [232 - 44•5]•4 - 44•1 = 232•4 - 44•21 = 232•4 - [276 - 232•1] •21 = 232•(25) - 276•(21)
Note : by applying the Euclidean algorithm we found a solution 232•(25) - 276•(21) = GCD (232, 276) and also 232•(25) + 276•( -21) = GCD (232, 276) Bézout's identity. Xoagus (talk) 13:54, 25 June 2013 (UTC)[reply]
Definition of GCD (a, b) : For each pair a ≤ b ε Z+ there exist GCD (a, b) with the following properties :
GCD (a, b) ε Z+.
If b = ak, k ε Z+ then GCD (a, b) = a. If b - ak1 = r1 we continu the long divisions according Euclid's algorithm with a - r1k2 = r2 ; r1 - r2k3 = r3 etc. ...... untill we get rn-1 - rnkn+1 = 0. Then GCD (a, b) = rn. (see example)
GCD (a, b) is a common divisor of a and b. (see example)
Each common divisor d of the numbers a and b is a divisor of GCD (a, b) (see example).
Moreover the Diophantin equation ax - by = GCD (a,b) has an unique solution (x, y) in Z+. (see example) Further the Diophantin equation ax + by = GCD (a, b) has a solution (even infinite many) in Z. (see example) 84.24.10.61 (talk) 14:48, 26 June 2013 (UTC) Xoagus (talk) 15:21, 26 June 2013 (UTC)[reply]
Are we still doing mathemetics ? 0 > 5 and thus -2 > 3? What is "0"? Is it the same as infinite ? If so is infinite a number ? What is the divisibility relation and what is the modified divisibility relation? Xoagus (talk) 18:50, 30 June 2013 (UTC)[reply]
The < I had in mind is ... < −3 < −2 < −1 < 1 < 2 < 3 < ... < 0.
And, for modified divisibility, I suggest:
aDbifa divides b and (b does not divide aor (a+b = 0 and b is positive))).
But, if you don't know what the "divisibility relation" is, you know enough to comment sensibly about GCD. Please return when you've read some elementary number theory textbooks. — Arthur Rubin(talk)19:26, 30 June 2013 (UTC)[reply]
The article introduces lengthy confusing explanations that make difficult to the reader to find where the algorithm is described. In particular, it seems that the editors of this article did ignore that an algorithm is like a theorem, it has to be stated separately from its explanation and its proof. The consequence, is that, although I have taught many times this algorithm, I am unable to decide, without a careful reading, if the algorithm(s) which is (are) described is(are) the one that is known under this name. What may understand a non-expert of the subject? I have rewritten the lead. I plan to rewrite the remainder of the article, but, because of the amount of needed work, I am not sure that this will be done soon. D.Lazard (talk) 16:42, 2 November 2013 (UTC)[reply]
The recursive algorithm that is presented is not a tail recursion. It follows that, if implemented, it needs an auxiliary memory (in the execution stack) which is not constant and is proportional to the number of recursive calls. It follows that the implementation of this code is not recommended, and as such is not notable. Even if notable, presenting it here would give it a undue weight. There is a tail recursive version of the algorithm, which involve a function with 6
parameters. Its construction from the iterative version of the algorithm is a standard programming exercise, which does not provides any encyclopedic insight to the subject of the article. I'll thus remove the present recursive version and not replacing it by the tail recursive version. However, if someone judges that the tail recursive version is really needed, I'll not oppose to its insertion. D.Lazard (talk) 15:23, 4 November 2013 (UTC)[reply]
I for one actually found the recursive method easier to understand (since the regular GCD algorithm is usually presented recursively) than the iterative method and would like it to remain for that reason. Modified like jbolden1517 suggests it helps understanding even further.
2001:6B0:1:1041:21D:E0FF:FE52:2EFF (talk) 16:49, 25 November 2013 (UTC)[reply]
Is the algorithm used to calculate safe? no overflow problem at all? For example, a program use all int type variables, then is the algorithm safe, we do not have to consider any possible overflow. Jackzhp (talk) 10:10, 20 April 2016 (UTC)[reply]
Please, do not edit other's post, and do not edit your posts after someone has answered, as you did recently.
Should the result be mentioned in the article? Actually it can simply be added to the "Proof" section by saying that an are increasing. --NeoUrfahraner (talk) 05:28, 5 May 2016 (UTC)[reply]
Yes, the result should be mentioned in the article. However, it deserve to be described in its own section, because of its important applications. Beside the overflow problem, that I find minor, it allows an accurate evaluation of the bit complexity of the algorithm. More important, this result is the basis of effective Thue's lemma, and therefore, it is commonly used for modular division and rational reconstruction. Also the polynomial analogue of this result makes easy to compute Padé approximants with the polynomial extended Euclidean algorithm. As you can see from the above links, a substantial editorial work is needed in this area. D.Lazard (talk) 14:55, 5 May 2016 (UTC)[reply]
I added the parts which IMHO can be simply added because they were already contained partially in the article. I agree that for further applications a section of its own wouldbe needed. --NeoUrfahraner (talk) 06:38, 6 May 2016 (UTC)[reply]
I ran into a very clever modular inverse that used an extended form of the binary GCD algorithm. I'm surprised it's not referenced here -- seems like a useful thing to include, especially next time someone wants to take a stab at improving the article. - Taral (talk) 21:04, 11 October 2020 (UTC)[reply]
Please, provide a reference. Without it, we cannot decide whether it is reliable and notable enough for being included in WP, and, if it is, to decide whether it must be included (here or in Modular inverse). In any case, this article lacks a section "Generalization". In fact, the method used to pass from the Euclidean algorithm to the extended algorithm can be applied to many gcd algorithms, even to algorithms that use fast multiplication. This must appear in the article. D.Lazard (talk) 21:23, 11 October 2020 (UTC)[reply]
Part of proof -- that s_{k+1} and t_{k+1} are the quotients of b and a by their GCD -- is inadequate
Viewing this as a Bézout's identity, this shows that and are coprime. The relation that has been proved above and Euclid's lemma shows that divides b and divides a. As they are coprime, they are, up to their sign the quotients of b and a by their greatest common divisor.
While the conclusion is true, the argument as currently written suggests that we only need to know that
in order to conclude that . However, this is not true: a counterexample is:
for which the above three conditions hold, but , so . It is in fact necessary to note that, in addition, and in order to make the desired conclusion. Without this, the proof is at best misleading and confusing, and at worst incorrect. My suggested replacement is:
Viewing this as a Bézout's identity, this shows that and are coprime. The relation from above is equivalent to , which by Euclid's lemma shows that
and , and hence ; and
and , and hence .
It also occurs to me that maybe might also not be obvious to readers, so it might be good to link to an article justifying this fact, if there is one.
"Inadequate" is too strong for a proof for which only one step is lacking. Nevertheless you are right that the proof is incomplete. However your edit, although correct and adapted for a textbook, is not convenient for an encyclopedy: to much formulas that hide the main points (in Wikipedia, the proofs that are given are here for emphasizing the main points; the reader to whom a detailed proof is needed can find it in a textbook). For these reasons, I'll modifiy this part of the proof as follows:
The relation that has been proved above and Euclid's lemma show that divides b, that is that for some integer d. Dividing by the relation gives So, and are coprime integers that are the quotients of a and b by a common factor, which is thus their greatest common divisor or its opposite.
Adding too many details in an encyclopedia is not always a good idea, since the useful details depend on the background and the way of thinking of the reader. D.Lazard (talk) 13:49, 24 October 2021 (UTC)[reply]
The run-time is used as further evidence that the alternate version of the extended gcd algorithm is less efficient than the first. There's a difference between "practical" optimization and big-O optimization. A quadratic algorithm might be practically faster because of how base operations are implemented in hardware or other constraints (memory access time, assembly instruction set, setup cost, etc.). Taking a hard stance about which implementation is better without any qualifications is false. I would recommend removing the latter sentences talking about optimization altogether. At best, a suggestion should be given as to what the various concerns are when picking algorithms for optimization purposes.
I thought I'd post my python code [based on pseudo-code] here just in case anyone runs into similar points of confusion.
def extended_euclidean_algorithm(a: int, b: int) -> tuple[tuple[int, int], int]:
"""For two ints, (a,b), solves: `a * x + b * y = gcd(a,b)`"""
(old_r, r) = (a, b)
(old_x, x) = (1, 0) # We will back out y at the end.
while r != 0:
quotient = old_r // r # "div" is just integer division!
(old_r, r) = (r, old_r - quotient * r)
(old_x, x) = (x, old_x - quotient * x)
# Assign the OLD values: when r==0 we've gone too far.
# If output the most recent `x`, then we'd get a * x + b * y == 0
# See esp. the example table.
x = old_x
gcd = old_r
# If "gcd < 0" then we know that's not true: If "gcd" is a
# common divisor, then so is -gcd>0.
# Relevant for negative numbers.
# This step is identical to multiplying both sides of the
# equation by -1.
if gcd < 0:
gcd *= -1
x *= -1
# Fill in y (coeff on b) now that we know other values.
if b != 0:
y = (gcd - x * a) // b
else:
y = 0
return (x, y), gcd Wobblesome (talk) 18:35, 7 September 2022 (UTC)[reply]
I'm not an expert in the field, although I did have some conviction over the edits given that's how I implemented the `inverse()` function (in Rust), with successful results. Given the edit was reverted, I would like to ask User:D.Lazard if you've had a chance to implement either versions of the pseudocode (my edit or the reverted version)? If you could provide some step by step examples of how the current version would work with negative numbers, for example, or if you have an implementation in any programming language I'd like to take a look.
This is my working Rust implementation
pub fn mod_mult_inv(a: &BigInt, n: &BigInt) -> Option<BigInt> {
if n < &BigInt::from(0) {
panic!("Expected `modulus` to be positive.");
}
// Ensure `a` is positive. The remaining code expects a positive `a` value.
let a: BigInt = if a > &BigInt::from(0) {
a.clone()
} else {
// If `a` is negative, find a positive congruent using Euclidean
// division. Using `a` or any of its congruents will result in the same
// value being returned from this function.
//
// Couldn't find a Euclidean division function, so using `mod_floor`
// which produces the same results for a positive modulus, as is the
// case here. See https://en.wikipedia.org/wiki/Modulo
a.mod_floor(n)
};
let mut t = BigInt::from(0);
let mut r = n.clone();
let mut new_t = BigInt::from(1);
let mut new_r = a.clone();
while new_r != BigInt::from(0) {
let quotient = &r / &new_r;
(t, new_t) = (new_t.clone(), &t - "ient * &new_t);
(r, new_r) = (new_r.clone(), &r - "ient * &new_r)
}
if r > BigInt::from(1) {
None
} else {
Some(t.mod_floor(&n))
}
}